Android上实现视频录制
尽管Google的SDK文档写到了相关的,内容但是实在是太短小精悍了,因为需要写个简单的Demo,所以学习了一下。
现在,我们一起来看看,到底要怎么去写吧:
首先,我们肯定要用到摄像头,因此需要在Manifest文件中声明使用权限:
<uses-permission android:name="android.permission.CAMERA" />
如果还要使用一些硬件属性,那还要做额外的声明,例如:
<uses-feature android:name="android.hardware.camera"/>
<uses-feature:name="android.hardware.camera.autofocus"/>
当然,你还想要录制音频的话,还得加上:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
当我们在录制的时候,通常都想要看到我们正在拍什么,这就需要预览,而预览需要在一个SurfaceView上实现,因此我们要添加一个控件:
<SurfaceView android:id="@+id/surface_camera" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true"
android:layout_weight="1">
</SurfaceView>
然后,我们来实现这个Activity:
public class CustomVideoCamera extends Activity implements SurfaceHolder.Callback{
private static final String TAG = "CAMERA_TUTORIAL";
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private Camera camera;
private boolean previewRunning;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_surface);
surfaceView = (SurfaceView) findViewById(R.id.surface_camera);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
if (camera != null){
Camera.Parameters params = camera.getParameters();
camera.setParameters(params);
}
else {
Toast.makeText(getApplicationContext(), "Camera not available!", Toast.LENGTH_LONG).show();
finish();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (previewRunning){
camera.stopPreview();
}
Camera.Parameters p = camera.getParameters();
p.setPreviewSize(width, height);
p.setPreviewFormat(PixelFormat.JPEG);
camera.setParameters(p);
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
previewRunning = true;
}
catch (IOException e) {
Log.e(TAG,e.getMessage());
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
previewRunning = false;
camera.release();
}
}
接着,我们就可以录制了:
private MediaRecorder mediaRecorder;
private final int maxDurationInMs = 20000;
private final long maxFileSizeInBytes = 500000;
private final int videoFramesPerSecond = 20;
public boolean startRecording(){
try {
camera.unlock();
mediaRecorder = new MediaRecorder();
mediaRecorder.setCamera(camera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
mediaRecorder.setMaxDuration(maxDurationInMs);
tempFile = new File(getCacheDir(),cacheFileName);
mediaRecorder.setOutputFile(tempFile.getPath());
mediaRecorder.setVideoFrameRate(videoFramesPerSecond);
mediaRecorder.setVideoSize(surfaceView.getWidth(), surfaceView.getHeight());
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mediaRecorder.setMaxFileSize(maxFileSizeInBytes);
mediaRecorder.prepare();
mediaRecorder.start();
return true;
} catch (IllegalStateException e) {
Log.e(TAG,e.getMessage());
e.printStackTrace();
return false;
} catch (IOException e) {
Log.e(TAG,e.getMessage());
e.printStackTrace();
return false;
}
}
停止拍摄,则:
public void stopRecording(){
mediaRecorder.stop();
camera.lock();
}
这样的话,通过编译之后,在Android OS 2.1 和 2.2上都能实现了,但在部分机器上会有些小问题,主要是预览上,看到app内的预览是另开线程做的,不知道是否会有改善?