2011-12-02

在 Android 裡使用麥克風錄音(MediaRecorder)

主角是 MediaRecorder,操作 API 與 MediaPlayer 大同小異,一併練習錄音、存到 SD 卡與從 SD 卡播放。

main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/recBtn"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick" />

    <Button
        android:id="@+id/playBtn"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick" />

</LinearLayout>
MediaRecorderActivity
public class MediaRecorderActivity extends Activity {

    private static final String TAG = "MediaRecorderActivity";
    private MediaRecorder mediaRecorder;
    private MediaPlayer mediaPlayer;
    private Button playBtn;
    private Button recBtn;
    private TextView tv;
    private boolean isRecording;
    private boolean isPlaying;
    private String filePath;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        this.insert2Tv("onCreate...", false);
        this.playBtn = (Button) this.findViewById(R.id.playBtn);
        this.recBtn = (Button) this.findViewById(R.id.recBtn);
        this.recBtn.setText("錄音");
        this.playBtn.setText("播放");
        this.playBtn.setEnabled(false);
    }

    public void onClick(View v) {
        this.insert2Tv("onClick...", false);
        switch (v.getId()) {
        case R.id.playBtn:
            if (this.isPlaying) {
                this.stopPlay();
            }
            else {
                // 開始播放
                this.mediaPlayer = new MediaPlayer();
                try {
                    this.mediaPlayer.setDataSource(this.filePath);
                    this.mediaPlayer.prepare();
                    this.mediaPlayer.start();
                    // 播放結束呼叫停止播放
                    this.mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

                        @Override
                        public void onCompletion(MediaPlayer mp) {
                            stopPlay();
                        }
                    });
                    this.isPlaying = true;
                    this.playBtn.setText("停止播放");
                    // 撥播中不可錄音
                    this.recBtn.setEnabled(false);
                    this.insert2Tv("播放中...");
                }
                catch (IOException e) {
                    Log.e(TAG, e.getMessage(), e);
                }
            }
            break;
        case R.id.recBtn:
            if (this.isRecording) {
                // 停止錄音
                this.mediaRecorder.stop();
                // 一定要釋放
                this.mediaRecorder.release();
                this.isRecording = false;
                this.recBtn.setText("錄音");
                // 錄音停止可播放
                this.playBtn.setEnabled(true);
                this.insert2Tv("錄音完成");
            }
            else {
                // 開始錄音
                this.mediaRecorder = new MediaRecorder();
                // 從麥克風收音
                this.mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                // 輸出 3gp 格式
                this.mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                // 編碼格式
                this.mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                // 輸出位置
                this.filePath = this.createFilePath();
                this.mediaRecorder.setOutputFile(this.filePath);
                try {
                    this.mediaRecorder.prepare();
                    this.mediaRecorder.start();
                    this.isRecording = true;
                    this.recBtn.setText("停止錄音");
                    // 錄音中不可播放
                    this.playBtn.setEnabled(false);
                    this.insert2Tv("錄音中...");
                }
                catch (IOException e) {
                    Log.e(TAG, e.getMessage(), e);
                }
            }
            break;
        }
    }

    private void stopPlay() {
        // 停止播放
        this.mediaPlayer.stop();
        this.mediaPlayer.release();
        this.isPlaying = false;
        this.playBtn.setText("播放");
        // 撥播停止可錄音
        this.recBtn.setEnabled(true);
        this.insert2Tv("停止播放");
    }

    private String createFilePath() {
        File sdCardDir = Environment.getExternalStorageDirectory();
        File cw1202 = new File(sdCardDir, "cw1202");
        if (!cw1202.exists()) {
            cw1202.mkdir();
        }
        String fileName = System.currentTimeMillis() + ".3gp";
        String path = new File(cw1202, fileName).getAbsolutePath();
        this.insert2Tv("輸出位置:" + path, false);
        return path;
    }

    private void insert2Tv(String msg) {
        this.insert2Tv(msg, true);
    }

    private void insert2Tv(String msg, boolean ui) {
        if (this.tv == null) {
            this.tv = (TextView) this.findViewById(R.id.tv);
        }
        if (ui) {
            this.tv.setText(msg);
        }
        Log.d(TAG, msg);
    }
}
在 AndroidManifest 加上 android.permission.RECORD_AUDIO 和 android.permission.WRITE_EXTERNAL_STORAGE 兩個權限就可以了。


相關文章

3 則留言:

  1. 請問在執行
    //設定音源
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    的時候,出現錯誤訊息視窗,這樣要如何排除??

    回覆刪除
  2. 請問在執行
    //設定音源
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    的時候,出現錯誤訊息視窗,這樣要如何排除??

    回覆刪除
  3. 請問在執行
    //設定音源
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    的時候,出現錯誤訊息視窗,這樣要如何排除??

    回覆刪除