1. 程式人生 > >android 呼叫系統自帶錄音實現,語音錄製與播放

android 呼叫系統自帶錄音實現,語音錄製與播放

相關許可權:

<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"> <Buttonandroid:text="播放錄音" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20dp" android:id="@+id/btn_three_play" /> <Buttonandroid: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() {
@Overridepublic 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;   
 }});