Разработка android приложения для записи звука

2623
Разработка android приложения для записи звука
Разработка android приложения для записи звука

В этом руководстве мы создадим базовое приложение для записи звука. Оно работает аналогично встроенному приложению Android recorder, но имеет очень простой пользовательский интерфейс.

ПРИМЕЧАНИЕ: Этот туториал предназначен для новичков и начинающих разработчиков Android. Я предполагаю, что вы уже знакомы с некоторыми основами программирования Android.

Вы узнаете о классе MediaRecorder, как получить разрешения пользователя (в Android M и выше) и как получить доступ к внешнему хранилищу на android.

Давайте начнем разработку!
Самый распространенный способ записи медиа — это класс MediaRecorder. В нашем файле MainActivity.java мы создадим myAudioRecorder из класса MedianRecorder. Мы предоставим ему источник звука (микрофон) и зададим формат вывода 3Gpp. Для хранения записи будем использовать место на внешнем хранилище.

private MediaRecorder myAudioRecorder;
output = Environment.getExternalStorageDirectory().getAbsolutePath() + "/myrecording.3gp";
myAudioRecorder = new MediaRecorder();
myAudioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myAudioRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myAudioRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
myAudioRecorder.setOutputFile(output);

Примечание: С каждой новой записью предыдущая будет удаляться, так как каждая запись записывается в один и тот же файл.

В случае если вы хотите сохранить все файлы, вы можете сохранить их в отдельных файлах. (Воспринимайте это как личное задание!)

Используются три кнопки:
1) START
2) STOP
3) PLAY

start = (Button)findViewById(R.id.button1);
stop = (Button) findViewById(R.id.button2);
play = (Button)findViewById(R.id.button3);
start.setOnClickListener(this);
stop.setOnClickListener(this);
play.setOnClickListener(this);

Функция прослушивания:

@Override public void onClick(View v){
switch (v.getId()){
case R.id.button1:
start(v);
break;
case R.id.button2:
stop(v);
break;
case R.id.button3:
try {
play(v);
}
catch (IOException e){
Log.i("IOException", "Error in play");
}
break;
default:
break;
}
}

Интуитивно понятно, что кнопки работают так, как они названы. Теперь мы присоединим объект myAudioRecorder к событиям onClickListener отдельных кнопок, чтобы начать и сохранить запись. Для кнопок START и STOP:

public void start(View view){
try{
myAudioRecorder.prepare();
myAudioRecorder.start();
}
catch (IllegalStateException e){
e.printStackTrace();
}
catch (IOException e){
e.printStackTrace();
}
start.setEnabled(false);
stop.setEnabled(true);
Toast.makeText(getApplicationContext(), "Recording started", Toast.LENGTH_SHORT).show();
}
public void stop(View view){
myAudioRecorder.stop();
myAudioRecorder.release();
myAudioRecorder = null;
stop.setEnabled(false);
play.setEnabled(true);
Toast.makeText(getApplicationContext(), "Audio recorded successfully", Toast.LENGTH_SHORT).show();
}

Toast показывает «Запись началась», когда начинается запись. Аналогично мы видим toast, когда запись сохраняется. Для PLAY мы прочитаем выходной файл и воспроизведем его через объект MediaPlayer. Снова отображается toast для воспроизведения аудио. Нам нужно добавить блоки try-catch в различных местах, чтобы избежать сбоев.

public void play(View view) throws IllegalArgumentException, SecurityException, IllegalStateException, IOException {
MediaPlayer m = new MediaPlayer();
m.setDataSource(output);
m.prepare();
m.start();
Toast.makeText(getApplicationContext(), "Playing audio", Toast.LENGTH_SHORT).show();
}

В UI (пользовательском интерфейсе) мы просто добавим три кнопки, как указано выше. Файл activity_main.xml выглядит следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.india.recorder.MainActivity">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="50dp"
        android:text="Start"
        android:id="@+id/button1"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="175dp"
        android:text="Stop"
        android:id="@+id/button2"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="300dp"
        android:text="Play"
        android:id="@+id/button3"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Welcome to Recorder!"
        android:layout_centerHorizontal="true"
        android:fontFamily="sans-serif"
        android:layout_marginTop="400dp"
        android:textSize="25dp"
        android:textColor="#008080"/>
</RelativeLayout>

Нам понадобятся разрешения пользователей для доступа к MIC и хранилищу, поэтому мы добавим разрешения в Android_Manifest.xml

ПРИМЕЧАНИЕ: Разрешения изменились в Android M. Теперь разрешения запрашиваются во время выполнения, а не во время установки, как это было в Android M.

Чтобы решить эту проблему, мы добавим проверку в наш код, чтобы определить версию Android mobile, с которой мы работаем, и действовать соответствующим образом.

@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case 200:
permissionToRecordAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
permissionToWriteAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
break;
}
if (!permissionToRecordAccepted ) MainActivity.super.finish();
if (!permissionToWriteAccepted ) MainActivity.super.finish();
}

Добавьте необходимые разрешения в Android.manifest для record_audio и file_storage.

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

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

Все должно работать, как ожидалось.

Полный файл MainActivity.java выглядит следующим образом:

package com.example.india.recorder;
import android.Manifest;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final int RECORD_AUDIO = 0;
private MediaRecorder myAudioRecorder;
private String output = null;
private Button start, stop, play;
private boolean permissionToRecordAccepted = false;
private boolean permissionToWriteAccepted = false;
private String [] permissions = {"android.permission.RECORD_AUDIO", "android.permission.WRITE_EXTERNAL_STORAGE"};
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int requestCode = 200;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissions, requestCode);
}
start = (Button)findViewById(R.id.button1);
stop = (Button) findViewById(R.id.button2);
play = (Button)findViewById(R.id.button3);
start.setOnClickListener(this);
stop.setOnClickListener(this);
play.setOnClickListener(this);
stop.setEnabled(false);
play.setEnabled(false);
output = Environment.getExternalStorageDirectory().getAbsolutePath() + "/myrecording.3gp";
myAudioRecorder = new MediaRecorder();
myAudioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myAudioRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myAudioRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
myAudioRecorder.setOutputFile(output);
}
@Override public void onClick(View v){
switch (v.getId()){
case R.id.button1:
start(v);
break;
case R.id.button2:
stop(v);
break;
case R.id.button3:
try {
play(v);
}
catch (IOException e){
Log.i("IOException", "Error in play");
}
break;
default:
break;
}
}
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case 200:
permissionToRecordAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
permissionToWriteAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
break;
}
if (!permissionToRecordAccepted ) MainActivity.super.finish();
if (!permissionToWriteAccepted ) MainActivity.super.finish();
}
public void start(View view){
try{
myAudioRecorder.prepare();
myAudioRecorder.start();
}
catch (IllegalStateException e){
e.printStackTrace();
}
catch (IOException e){
e.printStackTrace();
}
start.setEnabled(false);
stop.setEnabled(true);
Toast.makeText(getApplicationContext(), "Recording started", Toast.LENGTH_SHORT).show();
}
public void stop(View view){
myAudioRecorder.stop();
myAudioRecorder.release();
myAudioRecorder = null;
stop.setEnabled(false);
play.setEnabled(true);
Toast.makeText(getApplicationContext(), "Audio recorded successfully", Toast.LENGTH_SHORT).show();
}
public void play(View view) throws IllegalArgumentException, SecurityException, IllegalStateException, IOException {
MediaPlayer m = new MediaPlayer();
m.setDataSource(output);
m.prepare();
m.start();
Toast.makeText(getApplicationContext(), "Playing audio", Toast.LENGTH_SHORT).show();
}
}
Разработка android приложения для записи звука
Разработка android приложения для записи звука
Разработка android приложения для записи звука
Разработка android приложения для записи звука