首先要自定义SurfaceView实时显示摄像头捕获的画面
SurfaceView非常强大,有双缓存机制,可以在子线程更新ui,在游戏开发中最常用,下面是自定义SurfaceView
仿照别人的博客写的地址忘记了
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "MySurfaceView";
public Camera mCamera;
private final SurfaceHolder mHolder;
public MySurfaceView(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
// 设置Surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到界面 在Android3.0之后弃用
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
/**
* 在SurviceView创建的时候调用
*
* @param holder
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
/**
* 在SurviceView大小改变是调用
*
* @param holder
* @param format
* @param width
* @param height
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mHolder.getSurface() == null) {
// 如果Surface为空,不继续操作
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
Log.d(TAG, "当Surface改变后,停止预览出错");
}
// 在预览前可以指定Camera的各项参数
// 重新开始预览
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "预览Camera出错");
}
}
/**
* 在SurviceView销毁的时候调用
*
* @param holder
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
下面就是使用相机了
首先检查设备是否有摄像头
/** 检查相机硬件 */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
//设备有摄像头
return true;
} else {
//设备没有摄像头
return false;
}
}
获取摄像头
/**
* 安全的方式获取摄像头
*/
public Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open();
} catch (Exception e) {
Toast.makeText(this, "摄像头不可用", Toast.LENGTH_SHORT).show();
return null;
}
return c;
}
if (checkCameraHardware(this)){
camera = getCameraInstance();
if (camera != null) {
//根据手机支持的图片的宽高,拍摄制定宽高的图片
Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes();
Camera.Size size = pictureSizes.get(0);
parameters.setPictureSize(size.width, size.height);
camera.setParameters(parameters);
mySurfaceView = new MySurfaceView(this, camera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mySurfaceView);
}else {
Toast.makeText(this, "摄像头不可用", Toast.LENGTH_SHORT).show();
return;
}
}else {
Toast.makeText(this, "没有找到摄像头", Toast.LENGTH_SHORT).show();
return;
}
拍照
//自动聚焦
camera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
//开始拍照
camera.takePicture(null, null, mPicture);
Toast.makeText(MainActivity.this, "拍照成功", Toast.LENGTH_SHORT).show();
}
});
拍完照片的照片数据通过回调方法获取
/**
* 拍照回调方法
*/
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// 获取Jpeg图片,并保存在sd卡上
file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".jpg");
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(data);
fos.close();
Log.d(TAG, "onPictureTaken: 保存图片成功" + file.getAbsolutePath());
} catch (Exception e) {
Log.d(TAG, "保存图片失败");
}
//重新预览
camera.startPreview();
}
};
最后别忘了释放相机资源
@Override
protected void onDestroy() {
// 回收Camera资源
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
super.onDestroy();
}
在开发的时候我遇到的最大的问题就是这段代码
//根据手机支持的图片的宽高,拍摄制定宽高的图片
Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes();
Camera.Size size = pictureSizes.get(0);
parameters.setPictureSize(size.width, size.height);
camera.setParameters(parameters);
拍摄的图片太大了,保存浪费时间拍摄界面会卡顿 ,指定拍摄照片的大小就可以了
希望能帮到你,有错误请提出来谢谢,