Android SurfaceView录像
引言
在开发Android应用程序时,我们经常需要使用摄像头来进行视频录制。而SurfaceView是一个用于在屏幕上绘制图像的视图,通常用于显示相机预览。在本篇文章中,我们将介绍如何使用Android的SurfaceView来录制视频。
准备工作
在开始之前,确保你已经创建了一个Android项目,并且具备基本的Android开发知识。同时,你还需要在AndroidManifest.xml文件中添加相应的权限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
这些权限将允许我们访问摄像头、录制音频和保存录像文件。
创建SurfaceView布局
首先,我们需要在布局文件中创建一个用于显示相机预览的SurfaceView。在activity_main.xml文件中添加如下代码:
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
初始化相机
接下来,在MainActivity.java中初始化相机。我们需要在onCreate()方法中添加以下代码:
private Camera mCamera;
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = findViewById(R.id.surfaceView);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.e(TAG, "Error setting camera preview: " + e.getMessage());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mSurfaceHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
Log.e(TAG, "Error stopping camera preview: " + e.getMessage());
}
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.e(TAG, "Error starting camera preview: " + e.getMessage());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
});
}
private static final String TAG = "MainActivity";
在上述代码中,我们打开了相机,并将预览显示在SurfaceView上。在SurfaceHolder的回调方法中,我们处理了SurfaceView的创建、改变和销毁事件。
录制视频
接下来,我们需要在MainActivity.java中添加方法来录制视频。我们将创建一个startRecording()方法来开始录制,以及一个stopRecording()方法来停止录制。添加以下代码:
private MediaRecorder mMediaRecorder;
private boolean isRecording = false;
private void startRecording() {
if (isRecording) {
return;
}
mCamera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mMediaRecorder.setOutputFile(getOutputMediaFile().toString());
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
try {
mMediaRecorder.prepare();
mMediaRecorder.start();
isRecording = true;
} catch (IOException e) {
Log.e(TAG, "Error starting MediaRecorder: " + e.getMessage());
}
}
private void stopRecording() {
if (!isRecording) {
return;
}
mMediaRecorder.stop();
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
mCamera.lock();
isRecording = false;
}
private File getOutputMediaFile() {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MOVIES), "MyVideos");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.e(TAG, "Failed to create directory.");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
return new File(media