在本例子中, 我们需要用继承一个类AsyncTask以实现后台运行的效果 。
它可以跟线程一样适用于简单的异步处理,而且不需要借助线程和Handler即可实现。
AsyncTask有以下几个可以实现的几个方法:
onPreExecute();
该方法在开始进行后台操作前会被UI thread调用, 我们可以在该方法上做些初始化工作。
doInBackground(params...) ;
该方法在onPreExcute方法后执行, 并且会运行在后台中, 主要实现一些耗时的工作, 并可以使用publishProgress方法来指示当前的进度。
onProgressUpdate();
在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
onPostExecute(Result),
在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.
为了正确的使用AsyncTask类,以下是几条必须遵守的准则:
1) Task的实例必须在UI thread中创建
2) execute方法必须在UI thread中调用
3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法
4) 该task只能被执行一次,否则多次调用时将会出现异常
doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参数。
接下来我们需要在该类中实例化两个重要的对象, 一个是AudioRecord, 用于录制声音。 而另一个是AudioTrack, 用于对声音的播放。
代码如下:
所需权限
<uses-permission android:name="android.permission.RECORD_AUDIO"> </uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
public class SpeechTestActivity extends Activity { private Button mStartButton; private Button mStopButton; private Button mPlayButton; private boolean isRecording = true; // 录制状态 private boolean isPlaying = false; // 播放状态 private File audioFile; // 声音文件 private RecordTask record; // 录制异步处理类 private PlayTask player; // 播放异步处理类 /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 我们需要用到开始、停止、播放三个按钮 mStartButton = (Button) findViewById(R.id.btnStart); mStopButton = (Button) findViewById(R.id.btnStop); mPlayButton = (Button) findViewById(R.id.btnPlay); mStartButton.setOnClickListener(btnListener); mStopButton.setOnClickListener(btnListener); mPlayButton.setOnClickListener(btnListener); // 将缓存文件建立在SD卡根目录中, 用于储存记录的声音 File fpath = new File("sdcard/"); fpath.mkdirs(); // 创建一个目录 try { // 创建文件 audioFile = File.createTempFile("recording", ".pcm", fpath); } catch (Exception e) { String strMsg = e.getMessage(); Log.i("i", strMsg); } } private Button.OnClickListener btnListener = new Button.OnClickListener() { @Override public void onClick(View v) { Button btn = (Button) v; switch (btn.getId()) { case R.id.btnStart: { record = new RecordTask(); record.execute(); } break; case R.id.btnPlay: { player = new PlayTask(); player.execute(); } break; case R.id.btnStop: { isRecording = false; } break; default: break; } } }; // 该异步处理实现类录音的实现 public class RecordTask extends AsyncTask<Void, Integer, Void> { @Override protected Void doInBackground(Void... params) { isRecording = true; try { // 创建一个输入输出流 DataOutputStream dos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream(audioFile))); // 获取缓冲区大小 // 录制频率Hz、录制通道、录制编码格式 int bufferSize = AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); // 实例化一个录制对象 AudioRecord record = new AudioRecord( MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); // 缓冲区 short[] buffer = new short[bufferSize]; // 开始录制 record.startRecording(); int r = 0; while (isRecording) { // 读出数据 int bufferReadResult = record .read(buffer, 0, buffer.length); for (int i = 0; i < bufferReadResult; i++) { // 写入流 dos.writeShort(buffer[i]); } // 为显示进度使用 publishProgress(new Integer(r)); r++; } record.stop(); dos.close(); } catch (Exception e) { // TODO: handle exception } return null; } protected void onProgressUpdate(Integer... progress) { // stateView.setText(progress[0].toString()); } } // 该异步处理实现类录音的播放 class PlayTask extends AsyncTask<Void, Integer, Void> { @Override protected Void doInBackground(Void... params) { isPlaying = true; int bufferSize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); // 缓冲区大小需要少于录制的大小 short[] buffer = new short[bufferSize / 4]; try { // 定义输入流,将音频写入到AudioTrack类中,实现播放 DataInputStream dis = new DataInputStream( new BufferedInputStream(new FileInputStream(audioFile))); // 实例化一个播放对象 AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM); // 开始播放 track.play(); // 由于AudioTrack播放的是流,所以,我们需要一边播放一边读取 while (isPlaying && dis.available() > 0) { int i = 0; while (dis.available() > 0 && i < buffer.length) { buffer[i] = dis.readShort(); i++; } // 然后将数据写入到AudioTrack中 track.write(buffer, 0, buffer.length); } track.stop(); dis.close(); } catch (Exception e) { // TODO: handle exception } return null; } } }