首页 » Android程序设计:第2版 » Android程序设计:第2版全文在线阅读

《Android程序设计:第2版》录制音频和视频

关灯直达底部

标准的支持录制的类是MediaRecorder。和Media Player类似,MediaRecorder在其生命周期内也会传递各种状态。这些状态如下所示(关于这些状态的更多详细信息,可以查看开发者网站中给出的状态图,http://developer.android.com/reference/android/media/MediaRecorder.html):

Initial

MediaRecorder类执行实例化。

Initialized

MediaRecorder执行了初始化,可以使用了。

DataSource Configured

对媒体资源(指定在哪里输出)进行配置。

Prepared

准备好MediaRecorder,用于记录。

Recording

正在执行记录。

Released

释放所有的资源。

要使用MediaRecorder,在清单文件中要设置某些许可:

·要支持视频记录,选择RECORD_VIDEO和CAMERA:


      <uses-permission android:name=/"android.permission.RECORD_VIDEO/"/>      <uses-permission android:name=/"android.permission.CAMERA/"/>  

·要记录音频,选择:


      <uses-permission android:name=/"android.permission.RECORD_AUDIO/"/>  

录制音频

有3种录制音频的方式。标准方式是使用MediaRecorder;最简单的方式是使用Intent;AudioRecorder可以直接从硬件缓冲区中录制。

MediaRecorder音频录制

首先,初始化MediaRecorder。然后设置数据源信息(音频输入源、输出格式、编码类型,在哪里录制文件等)。从版本8开始,还可以设置比特率和样本比率。完成这些后,调用prepare方法。


// initialize the MediaRecorderMediaRecorder mediarecorder = new MediaRecorder;// configure the data source    // the source of the audio input    mediarecorder.setAudioSource(MediaRecorder.AudioSource.MIC);    // output format    mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);    // encoding    mediarecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);    // use absolute path to file where output is stored    mediarecorder.setOutputFile(/"/sdcard/audiorecordexample.3gpp/");    // prepare to record    mediarecorder.prepare;  

然后,当需要启动录制时,执行start方法:


mediarecorder.start;  

要停止录制,可以调用stop方法。如果后来又想继续录制,则可以调用reset方法强制MediaRecorder回到空闲状态。然后重新配置数据源,再次准备MediaRecorder:


mediarecorder.stop;...mediarecorder.reset;  

一旦不再需要MediaRecorder,要记得释放它:


mediarecorder.release;  

下面是一个简单的应用示例,它为用户提供record按钮。单击该按钮,record方法会在已经指向的文件路径下录制。然后,会显示stop按钮,record按钮会变得不可见。当单击stop按钮时,会调用stopRecord方法,又重新显示record按钮。


public class AudioRecorder extends Activity {    private MediaRecorder mediarecorder;    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.audiorecorderlayout);        ImageButton recordbutton = (ImageButton) findViewById(R.id.record);        recordbutton.setOnClickListener(new OnClickListener {            public void onClick(View v) {                record(/"/sdcard/audiorecordexample.3gpp/");            }        });        ImageButton stopbutton = (ImageButton) findViewById(R.id.stop);        stopbutton.setOnClickListener(new OnClickListener {            public void onClick(View v) {                stopRecord;            }        });    }    private void record(String filePath) {            try {                File mediafile = new File(filePath);                if(mediafile.exists) {                    mediafile.delete;                }                mediafile = null;                // record button goes away                ImageButton button = (ImageButton) findViewById(R.id.record);                button.setVisibility(View.GONE);                    // stop button shows up                ImageButton stopbutton = (ImageButton) findViewById(R.id.stop);                stopbutton.setVisibility(View.VISIBLE);                    // set up media recorder                if(mediarecorder == null) mediarecorder = new MediaRecorder;                mediarecorder.setAudioSource(MediaRecorder.AudioSource.MIC);                mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);                mediarecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);                mediarecorder.setOutputFile(filePath);                    // prepare media recorder                mediarecorder.prepare;                    // start media recorder                mediarecorder.start;            } catch (Exception e) {                e.printStackTrace;            }        }    }    private void stopRecord {                    // stop media recorder                mediarecorder.stop;                    // reset media recorder                mediarecorder.reset;                // record button shows up                ImageButton button = (ImageButton) findViewById(R.id.record);                button.setVisibility(View.VISIBLE);                // stop button goes away                ImageButton stopbutton = (ImageButton) findViewById(R.id.stop);                stopbutton.setVisibility(View.GONE);    }} 

使用Intent录制音频

通过Intent录制是最简单的方式。只需要构建Media Store.Audio.Media.RECORD_SOUND_ACTION intent,然后在Activity内调用startActivityForResult方法启动它,它会启动在大多数Android设备中都会提供的默认音频录制程序,继续录制一些音频:


Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);startActivityForResult(intent, 1); // intent and requestCode of 1  

录制完成后,音频录制程序结束,启动调用startActivityForResult方法的Activity会到前端执行。当发生这种情况时,会触发Activity的onActivityResult方法,其中包括了我们提供的requestCode代码(在这个例子中,即1),结果代码(OK或error),以及包含指向记录的音频文件的intent:


protected void onActivityResult(int requestCode, int resultCode, Intent intent) {    // is it our requestCode?    if (requestCode == 1) {        // is the resultCode OK?      if (resultCode == RESULT_OK) {                // lets get the uri              Uri audioUri = intent.getData;                // lets play the uri or do something with it.              playAudio(audioUri);         }    }}  

AudioRecorder音频录制

和AudioTrack类似,AudioRecorder提供了更直接的录制体验:


short buffer = new short[10000];recorder = new AudioRecord( // source to record from                    MediaRecorder.AudioSource.MIC,                            // frequency                    11025,                            // channel config—mono, stereo, etc.                    AudioFormat.CHANNEL_CONFIGURATION_MONO,                            // audio encoding                    AudioFormat.ENCODING_PCM_16BIT,                            // buffer size                    buffer.length                );  

AudioRecord方法提供了需要录制的音频资源类型(话筒、摄像机话筒、或语音呼叫)、以Hz表示的采样比率(44100、22050或11025)、音频配置(单声道或立体声)、音频格式/编码、以字节数表示的缓冲区长度。注意,缓冲区的大小决定了AudioRecord在读取运行数据之前能够录制的时间。数据应该从音频硬件中读取,以小于总录制缓冲区的大小读取。Android的AudioRecord一旦配置完成,会自动知道如何使用设备上的硬件接口,从而提供愉快的用户体验。

为开始录制,设置AudioRecord的Record状态,重复从硬件缓冲区中读取数据:


recorder.startRecording;while(recordablestate) {    try {        // read in up to buffer size        int readBytes = recorder.read(buffer, 0, buffer.length);        // do something with the bytes that are read        } catch (Exception t) {          recordablestate = false;        }}  

要停止录制,将AudioRecord的状态置为Stop。如果不想录制,则不要忘记释放和录制相关的所有资源。如果还想继续录制,可以调用startRecording方法再开始录制:


// stop recordingrecorder.stop;// release recording resourcesrecorder.release;  

视频录制

可以通过两种方式录制视频:通过使用MediaRecorder或通过使用Intent。不支持类似音频那样的原始录制。

MediaRecorder视频录制

通过MediaRecorder录制视频的过程和录制音频的过程非常相似:初始化MediaRecorder,准备数据源,启动MediaRecorder。可以给用户提供预览窗口,这样他可以预览捕捉到的视频,通过提供之前提到的surface来播放视频。一般来说,会使用VideoView:


// initializeMediaRecorder mediarecorder = new MediaRecorder;// set data sourcemediarecorder.setAudioSource(MediaRecorder.AudioSource.MIC);mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);mediarecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);mediarecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);mediarecorder.setOutputFile(/"/sdcard/someexamplevideo.mp4/");// provide a surface to show the preview in. in this case a VideoView is usedvideoview = (VideoView) findViewById(R.id.videosurface);SurfaceHolder holder = videoview.getHolder;mediarecorder.setPreviewDisplay(holder.getSurface);// preparemediarecorder.prepare;// start recordingmediarecorder.start;  

intent视频录制

基于intent的视频录制和使用intent录制音频类似。要使用的intent是MediaStore.ACTION_VIDEO_CAPTURE,结果数据是视频文件的URI。