首先调用手机系统自带的录音功能需要相关权限以及读写SD卡的权限
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
添加布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="example.com.recorder.MainActivity">
<Button
android:text="播放录音"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20dp"
android:id="@+id/btn_three_play" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btn_three_recorder"
android:textSize="20dp"
android:text="开始录音并保存" />
<TextView
android:id="@+id/tv_progress3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="40sp"
android:textStyle="bold"
android:text="0"/>
</LinearLayout>
MainActivity.class 代码如下
public class MainActivity extends Activity implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener {
private MediaPlayer mediaPlayer;
private boolean isRecording = false;
private TextView mTv_progress3;
Button btn_three_play, btn_three_recorder;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_three_play = (Button) findViewById(R.id.btn_three_play);
btn_three_recorder = (Button) findViewById(R.id.btn_three_recorder);
mTv_progress3 = (TextView) findViewById(R.id.tv_progress3);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnPreparedListener(this);
btn_three_play.setEnabled(false);
btn_three_play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
playRecorder();
}
});
btn_three_recorder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
recorder_Audio();
btn_three_play.setEnabled(true);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
private boolean isPlaying = false;
private int frequency = 11025;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int audiosource = MediaRecorder.AudioSource.MIC;
int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
File recordingFile = null;
MainActivity.RecordAudio recordAudio = null;
MainActivity.PlayAudio playAudio = null;
public void recorder_Audio() throws IOException {
//AudioRecord不会直接保存音频,需要自己保存
File path = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
path.mkdirs();
try {
recordingFile = File.createTempFile("recording", ".pcm", path);
} catch (IOException e) {
e.printStackTrace();
}
recordAudio = new MainActivity.RecordAudio();
recordAudio.execute();
}
public void playRecorder() {
isRecording = false;
playAudio = new MainActivity.PlayAudio();
playAudio.execute();
}
public void onCompletion(MediaPlayer mp) {
}
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
private class PlayAudio extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... params) {
isPlaying = true;
int bufferSize = AudioTrack.getMinBufferSize(frequency, channelConfig, audioFormat);
short[] buffer = new short[bufferSize / 4];
DataInputStream dis = null;
try {
dis = new DataInputStream(new BufferedInputStream(new FileInputStream(recordingFile)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, frequency, channelConfig, audioFormat, bufferSize, AudioTrack.MODE_STREAM);
audioTrack.play();
try {
while (isPlaying && dis.available() > 0) {
int i = 0;
while (dis.available() > 0 && i < buffer.length) {
buffer[i] = dis.readShort();
i++;
}
audioTrack.write(buffer, 0, buffer.length);
}
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
Toast.makeText(MainActivity.this, "语音开始播放", Toast.LENGTH_SHORT).show();
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Toast.makeText(MainActivity.this, "语音播放完了", Toast.LENGTH_SHORT).show();
}
}
private class RecordAudio extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... params) {
isRecording = true;
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(recordingFile)));
int bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfig, audioFormat);
AudioRecord audioRecord = new AudioRecord(audiosource, frequency, channelConfig, audioFormat, bufferSize);
short[] buffer = new short[bufferSize];
audioRecord.startRecording();
int r = 0;
while (isRecording) {
int bufferReadResult = audioRecord.read(buffer, 0, bufferSize);
for (int i = 0; i < bufferReadResult; i++) {
try {
dos.writeShort(buffer[i]);
} catch (IOException e) {
e.printStackTrace();
}
}
publishProgress(new Integer(r));
r++;
}
audioRecord.stop();
dos.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
Toast.makeText(MainActivity.this, "正在录音", Toast.LENGTH_SHORT).show();
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
mTv_progress3.setText(values[0] + "");
}
}
}
其中先设置播放按钮为不可点击,录音后才可点击,不然会报空指针异常
或者可以用按住录音 松开播放来实现 代码如下
btn_three_recorder.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN: //按下
try {
recorder_Audio();
} catch (IOException e) {
e.printStackTrace();
}
break;
case MotionEvent.ACTION_MOVE: //移动
break;
case MotionEvent.ACTION_UP: //抬起
playRecorder();
break;
}
return true;
}
});