(一)通过意图捕获音频

适合录制无须过多处理的音频,其中很少有或没有编程控制的需要

package fly.fei;

 

import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
 
public class IntentAudioRecorder extends Activity implements
android.view.View.OnClickListener, OnCompletionListener {
 
public static int RECODE_REQUEST = 77;// 传递给StartActivityForResult函数,从而确定任何OnActivityResult调用
 
Button createRecording, playRecording;// 两个按丢
 
Uri audioFileUri;// Uri同一资源标记符。一个Uri对象包含将由录音器活动录制的音频文件的URI
 
/**
构造器
 */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_audio_recorder);
 
createRecording = (Button) this.findViewById(R.id.RecordButton);
createRecording.setOnClickListener(this);
 
playRecording = (Button) this.findViewById(R.id.PlayButton);
playRecording.setOnClickListener(this);
playRecording.setEnabled(false);
}
 
/**
菜单
 */
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_intent_audio_recorder, menu);
return true;
}
 
/**
结束回调函数
 */
public void onCompletion(MediaPlayer mp) {
playRecording.setEnabled(true);
}
 
/**
点击事件监听器
 */
 
public void onClick(View v) {
if (v == createRecording) {
Intent intent = new Intent(
MediaStore.Audio.Media.RECORD_SOUND_ACTION);
startActivityForResult(intent, RECODE_REQUEST);
 
} else if (v == playRecording) {
MediaPlayer mediaPlayer = MediaPlayer.create(this, audioFileUri);
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.start();
playRecording.setEnabled(false);
}
}
 
/**
结果回调函数
 */
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == RECODE_REQUEST) {
audioFileUri = data.getData();
playRecording.setEnabled(true);
}
}
}

 

 

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
 
        <Button
            android:id="@+id/RecordButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="录制" />
 
        <Button
            android:id="@+id/PlayButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="播放" />
 
    </LinearLayout>

(二)MediaRecord和MediaPlayer

定制音频捕获

能够获得更大的灵活性,允许控制录制媒体的时间长度以及其他要素,但是将界面留给我们来实现

package fly.fei;

 

import java.io.File;
import java.io.IOException;
 
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
 
public class IntentAudioRecorder extends Activity implements
android.view.View.OnClickListener, OnCompletionListener {
 
TextView statusTextView;// 状态显示
 
Button startRecording, stopRecording, playRecording, finishButton;// 录制,完成,播放,结束按钮
 
MediaRecorder recorder;// 媒体录制器
MediaPlayer player;// 媒体播放器
 
File audioFile;// 音频文件
 
/**
构造器
 */
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_audio_recorder);
 
init();// 初始化
}
 
/**
初始化控件
 */
private void init() {
statusTextView = (TextView) this.findViewById(R.id.StatusTextView);
 
startRecording = (Button) this.findViewById(R.id.StartRecording);
stopRecording = (Button) this.findViewById(R.id.StopRecording);
playRecording = (Button) this.findViewById(R.id.PlayRecording);
finishButton = (Button) this.findViewById(R.id.FinishButton);
 
startRecording.setOnClickListener(this);
stopRecording.setOnClickListener(this);
playRecording.setOnClickListener(this);
finishButton.setOnClickListener(this);
 
stopRecording.setEnabled(false);
playRecording.setEnabled(false);
}
 
/**
结束回调函数
 */
public void onCompletion(MediaPlayer mp) {
playRecording.setEnabled(true);
stopRecording.setEnabled(false);
startRecording.setEnabled(false);
statusTextView.setText("准备");
}
 
/**
点击监听事件
 */
public void onClick(View v) {
if (v == finishButton) {// 结束
finish();
 
} else if (v == stopRecording) {// 完成
recorder.stop();// 停止录制
recorder.release();// 释放媒体录制器资源
 
player = new MediaPlayer();// 新建媒体播放器
player.setOnCompletionListener(this);// 回调
 
try {
player.setDataSource(audioFile.getAbsolutePath());// 要播放的媒体资源,文件的绝对路径
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
 
try {
player.prepare();// 播放器准备好,等待播放
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
 
statusTextView.setText("准备录制");
 
playRecording.setEnabled(true);
stopRecording.setEnabled(false);
startRecording.setEnabled(true);
 
} else if (v == startRecording) {
recorder = new MediaRecorder();// 新建媒体录制器
// 录制器相关设置
 
// 录制器的音频源
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
// 录制器输出格式。THREE_GPP:.3gp 可能同时包含音频和视频轨
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
// 设置编解码器。AMR_NB自适应多速率窄带编解码器,只针对语音进行优化,采样率8kHz,码率4.75-12.2kbps
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
 
File path = new File(Environment.getExternalStorageDirectory()// 新建路径
.getAbsolutePath() + "/Android/data/fly/fei/files/");
path.mkdirs();// 创建路径
 
try {
audioFile = File.createTempFile("recording", ".3gp", path);// 创建指定路径下的文件
} catch (IOException e) {
e.printStackTrace();
}
 
recorder.setOutputFile(audioFile.getAbsolutePath());// 指定录制器输出的文件
 
try {
recorder.prepare();// 录制器准备好录制
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
 
recorder.start();// 开始录制
statusTextView.setText("录制中");
 
playRecording.setEnabled(false);
stopRecording.setEnabled(true);
startRecording.setEnabled(false);
 
} else if (v == playRecording) {// 播放
player.start();
statusTextView.setText("播放中");
playRecording.setEnabled(false);
stopRecording.setEnabled(false);
startRecording.setEnabled(false);
}
}
 
}

 

 

   

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
 
        <TextView
            android:id="@+id/StatusTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView" />
 
        <Button
            android:id="@+id/StartRecording"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="录制" />
 
        <Button
            android:id="@+id/StopRecording"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="完成" />
 
        <Button
            android:id="@+id/PlayRecording"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="播放" />
 
        <Button
            android:id="@+id/FinishButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="结束" />
 
    </LinearLayout>

 

(三)AudioRecord和AudioTrack

录制原始样本

可获得最大的控制性和灵活性,但是需要完成捕获和使用音频的大部分工作,可实现任何类型的音频处理或者需要合成音频

 

package fly.fei;

 

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.R.integer;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
 
public class IntentAudioRecorder extends Activity implements
android.view.View.OnClickListener {
 
TextView statusTextView;// 状态显示
 
Button startRecordingButton, stopRecordingButton, startPlaybackButton,
stopPlaybackButton;// 录制,完成,播放,结束按钮
 
RecordAudio recordTask;// 内部类 --录制
PlayAudio playTask;// 内部类 ------播放
 
File recordingFile;// 音频文件
// 布尔跟踪
boolean isRecording = false;// 是否录制
boolean isPlaying = false;// 是否播放
// Audio对象配置设置
int frequency = 11025;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
 
/**
构造器
 */
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_audio_recorder);
 
init();// 初始化
}
 
/**
初始化控件
 */
private void init() {
statusTextView = (TextView) this.findViewById(R.id.StatusTextView);
// 获得按钮
startRecordingButton = (Button) this
.findViewById(R.id.StartRecordingButton);
stopRecordingButton = (Button) this
.findViewById(R.id.StopRecordingButton);
 
startPlaybackButton = (Button) this
.findViewById(R.id.StartPlaybackButton);
stopPlaybackButton = (Button) this
.findViewById(R.id.StopPlaybackButton);
// 设置监听器
startRecordingButton.setOnClickListener(this);
stopRecordingButton.setOnClickListener(this);
startPlaybackButton.setOnClickListener(this);
stopPlaybackButton.setOnClickListener(this);
// 设置按钮状态
stopRecordingButton.setEnabled(false);
startPlaybackButton.setEnabled(false);
stopPlaybackButton.setEnabled(false);
// 新建路径
File path = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/Android/data/fly/fei/files/");
path.mkdirs();
 
try {
recordingFile = File.createTempFile("recording2", ".pcm", path);// 创建pcm文件
} catch (IOException e) {
e.printStackTrace();
}
}
 
/**
点击监听事件
 */
public void onClick(View v) {
if (v == startRecordingButton) {
record();
} else if (v == stopRecordingButton) {
stopRecording();
} else if (v == startPlaybackButton) {
play();
} else if (v == stopPlaybackButton) {
stopPlaying();
}
}
 
private void stopPlaying() {
isPlaying = false;
 
stopPlaybackButton.setEnabled(false);
startPlaybackButton.setEnabled(true);
}
 
private void play() {
startPlaybackButton.setEnabled(true);
 
playTask = new PlayAudio();
playTask.execute();
 
stopPlaybackButton.setEnabled(true);
}
 
private void stopRecording() {
isRecording = false;
}
 
private void record() {
startRecordingButton.setEnabled(false);
stopRecordingButton.setEnabled(true);
 
startPlaybackButton.setEnabled(true);
 
recordTask = new RecordAudio();
recordTask.execute();
}
 
/**
播放内部类
 * 
 * @author Administrator
 * 
 */
private class PlayAudio extends AsyncTask<Void, integer, Void> {
protected Void doInBackground(Void... params) {
isPlaying = true;
 
int bufferSize = AudioTrack.getMinBufferSize(frequency,
channelConfiguration, audioEncoding);
short[] audiodata = new short[bufferSize / 4];
 
try {
DataInputStream dis = new DataInputStream(//PCM数据文件的流对象
new BufferedInputStream(new FileInputStream(
recordingFile)));
 
AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC, frequency,// 流类型,音频采样率
channelConfiguration, audioEncoding, bufferSize,// 通道配置,音频格式
AudioTrack.MODE_STREAM);// 模式。MODE_STATIC播放前将所有数据转到AudioTrack中;MODE_SRREAM播放时将数据持续转移到AudioTrack中
audioTrack.play();
//一旦构造了AudioTrack,就需要打开音频源,将音频数据读取到缓冲区,并将它传递给AudioTrack对象
while (isPlaying && dis.available() > 0) {
int i = 0;
while (dis.available() > 0 && i < audiodata.length) {
audiodata[i] = dis.readShort();
i++;
}
audioTrack.write(audiodata, 0, audiodata.length);
}
dis.close();
 
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
 
return null;
}
 
/**
开始前调用
 */
protected void onPreExecute() {
super.onPreExecute();
startPlaybackButton.setEnabled(false);
stopPlaybackButton.setEnabled(true);
}
 
}
 
/**
录制内部类
 * 
 * @author Administrator
 * 
 */
private class RecordAudio extends AsyncTask<Void, integer, Void> {
protected Void doInBackground(Void... params) {
isRecording = true;
 
try {
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream(
recordingFile)));
 
int bufferSize = AudioRecord.getMinBufferSize(frequency,
channelConfiguration, audioEncoding);
 
AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC, frequency,
channelConfiguration, audioEncoding, 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++) {
dos.writeShort(buffer[i]);
}
 
// publishProgress(new Integer(r));//不能再AsyncTack中改变UI,否则出错
// r++;
 
}
Log.e("record", "stop");
audioRecord.stop();
dos.close();
 
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
 
return null;
}
 
// private void publishProgress(Integer integer) {
// statusTextView.setText(integer.toString());
// }
/**
结束后调用
 */
protected void onPostExecute(Void result) {
super.onPostExecute(result);
startRecordingButton.setEnabled(true);
stopRecordingButton.setEnabled(false);
startPlaybackButton.setEnabled(true);
}
}
}
 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
 
        <TextView
            android:id="@+id/StatusTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView" />
 
        <Button
            android:id="@+id/StartRecordingButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="录制" />
 
        <Button
            android:id="@+id/StopRecordingButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="完成" />
 
        <Button
            android:id="@+id/StartPlaybackButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="播放" />
 
        <Button
            android:id="@+id/StopPlaybackButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="停止" />
 
    </LinearLayout>