个人封装的一个Camera类

好久不写博客了,代码写了不少,但大多数都是拿来主义,要不是网上,要不就是自己曾经的代码拼装。

新工作是搞Android开发的,近期任务要求我封装一个Carmera类,自己也认为还是封装以后方便使用,弄了半天写好一个,能够调用手机前置后置摄像头进行拍照摄像,并能够依据设置相机各种參数,进行保存。发到这里分享下。


package com.hourglass.camerademo;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;

/**
 * 拍照录像封装类
 * 
 * @author Hourglass 2014年4月21日 Q331956750
 * @version 1.2
 */
public class MediaCamera {
	private static int cameraPosition = Camera.CameraInfo.CAMERA_FACING_FRONT;

	private static String tag = "MediaCamera---------------------";

	private static int back_PictureWidth;
	private static int back_PictureHeight;
	private static int back_PreviewWidth;
	private static int back_PreviewHeight;
	private static int back_degrees;
	private static String back_FocusMode;
	private static int back_pixel_format;

	private static int front_PictureWidth;
	private static int front_PictureHeight;
	private static int front_PreviewWidth;
	private static int front_PreviewHeight;
	private static int front_degrees;
	private static String front_FocusMode;
	private static int front_pixel_format;

	private static int back_output_format;
	private static int back_video_encoder;
	private static int back_Video_width;
	private static int back_Video_height;
	private static int back_Video_rate;

	private static int front_output_format;
	private static int front_video_encoder;
	private static int front_Video_width;
	private static int front_Video_height;
	private static int front_Video_rate;

	private Bitmap mBitmap = null;

	private MediaRecorder mediarecorder;
	public boolean isRecording;

	private static String DefaultImagePath = Environment
			.getExternalStorageDirectory().getPath() + "/Pictures/";
	private static String DefaultImageName = "Image";
	private static String DefaultVedioPath = Environment
			.getExternalStorageDirectory().getPath() + "/Pictures/";
	private static String DefaultVedioName = "Video";

	private Camera camera = null;
	private SurfaceView surfaceView = null;
	private SurfaceHolder surfaceHolder = null;

	public MediaCamera(SurfaceView surfaceView) {
		super();
		this.surfaceView = surfaceView;
		surfaceHolder = surfaceView.getHolder();
		surfaceHolder.addCallback(surfaceHolderCallback);
		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
			surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
	}

	/******************************* 静态检測类 ********************************************/
	/**
	 * 检測设备是否有摄像头
	 * 
	 * @param context
	 *            执行上下文
	 * @return 若有摄像头 返回true 若无返回false
	 */
	public static boolean checkCameraHardware(Context context) {
		return context.getPackageManager().hasSystemFeature(
				PackageManager.FEATURE_CAMERA) ? true : false;
	}

	/**
	 * 检測设备SD卡状态
	 * 
	 * @return 正常返回true 不正常返回false
	 */
	public static boolean checkDeviceSDEnable() {
		return android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED) ? true : false;
	}

	/**
	 * 检測设备SD卡剩余空间
	 * 
	 * @return 单位MB
	 */
	public static long getSDFreeSize() {
		// 取得SD卡文件路径
		File path = Environment.getExternalStorageDirectory();
		StatFs sf = new StatFs(path.getPath());
		// 获取单个数据块的大小(Byte)
		long blockSize = sf.getBlockSize();
		// 空暇的数据块的数量
		long freeBlocks = sf.getAvailableBlocks();
		// 返回SD卡空暇大小
		// return freeBlocks * blockSize; //单位Byte
		// return (freeBlocks * blockSize)/1024; //单位KB
		return (freeBlocks * blockSize) / 1024 / 1024; // 单位MB
	}

	/**
	 * 检測设备SD卡总容量
	 * 
	 * @return 单位MB
	 */
	public static long getSDAllSize() {
		// 取得SD卡文件路径
		File path = Environment.getExternalStorageDirectory();
		StatFs sf = new StatFs(path.getPath());
		// 获取单个数据块的大小(Byte)
		long blockSize = sf.getBlockSize();
		// 获取全部数据块数
		long allBlocks = sf.getBlockCount();
		// 返回SD卡大小
		// return allBlocks * blockSize; //单位Byte
		// return (allBlocks * blockSize)/1024; //单位KB
		return (allBlocks * blockSize) / 1024 / 1024; // 单位MB
	}

	/******************************* 静态检測类结束 ********************************************/
	/**
	 * 打开或切换前后摄像头
	 */
	public void OpenCamera() {
		int cameraCount = 0;
		CameraInfo cameraInfo = new CameraInfo();
		cameraCount = Camera.getNumberOfCameras();
		for (int i = 0; i < cameraCount; i++) {
			Camera.getCameraInfo(i, cameraInfo);
			releaseCamera();
			if (cameraPosition == Camera.CameraInfo.CAMERA_FACING_FRONT) {
				// 如今是后置,变更为前置
				cameraPosition = Camera.CameraInfo.CAMERA_FACING_BACK;
				try {
					camera = Camera.open(cameraPosition);
					camera.setPreviewDisplay(surfaceHolder);
				} catch (Exception e) {
					Log.d(tag, "前置相机无法打开或正在被占用");
				}
				try {
					setCameraParameters(camera, 1);
				} catch (Exception e) {
					e.printStackTrace();
					Log.d(tag, "前置相机无法设置參数");
				}
				camera.startPreview();
				break;
			} else {
				// 如今是前置, 变更为后置
				cameraPosition = Camera.CameraInfo.CAMERA_FACING_FRONT;
				try {
					camera = Camera.open(cameraPosition);
					camera.setPreviewDisplay(surfaceHolder);
				} catch (Exception e) {
					Log.d(tag, "后置相机无法打开或正在被占用");
				}
				try {
					setCameraParameters(camera, 0);
				} catch (Exception e) {
					e.printStackTrace();
					Log.d(tag, "前置相机无法设置參数");
				}
				camera.startPreview();
				break;
			}
		}
	}

	/**
	 * Camera拍照
	 * 
	 * @param Suffix
	 *            生成JPEG 0 生成PNG 1
	 */
	public void takePhoto(int Suffix) {
		if (camera != null) {
			try {
				if (Suffix == 0)
					camera.takePicture(null, null, JpegCallback);
				else
					camera.takePicture(null, null, PngCallback);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		camera.startPreview();
	}

	/**
	 * JPEG回调方法
	 * **/
	private PictureCallback JpegCallback = new PictureCallback() {
		public void onPictureTaken(byte[] data, Camera camera) {
			if (null != data) {
				mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

			}
			Matrix matrix = new Matrix();
			matrix.postRotate((float) 0.0);
			Bitmap rotaBitmap = Bitmap.createBitmap(mBitmap, 0, 0,
					mBitmap.getWidth(), mBitmap.getHeight(), matrix, false);
			if (null != rotaBitmap) {
				savePicture(rotaBitmap, DefaultImagePath,
						Bitmap.CompressFormat.JPEG, DefaultImageName, ".jpeg");
			}
		}
	};
	/**
	 * Png回调方法
	 * **/
	private PictureCallback PngCallback = new PictureCallback() {
		public void onPictureTaken(byte[] data, Camera camera) {
			if (null != data) {
				mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
			}
			Matrix matrix = new Matrix();
			matrix.postRotate((float) 0.0);
			Bitmap rotaBitmap = Bitmap.createBitmap(mBitmap, 0, 0,
					mBitmap.getWidth(), mBitmap.getHeight(), matrix, false);
			if (null != rotaBitmap) {
				savePicture(rotaBitmap, DefaultImagePath,
						Bitmap.CompressFormat.PNG, DefaultImageName, ".png");
			}
		}
	};

	/**
	 * 保存Bitmap
	 * 
	 * @param bitmap
	 * @param savePath
	 * @param format
	 *            编码格式
	 * @param filename
	 *            文件名称 Null则依照当前毫秒命名
	 * @param suffix
	 *            后缀名
	 */
	private void savePicture(Bitmap bitmap, String savePath,
			CompressFormat format, String filename, String suffix) {
		File folder = new File(savePath);
		if (!folder.exists()) {
			folder.mkdir();
		}
		String jpegName;
		if (filename == null || filename.length() == 0)
			jpegName = savePath + System.currentTimeMillis() + suffix;
		else {
			jpegName = savePath + filename + suffix;
		}
		try {
			FileOutputStream fout = new FileOutputStream(jpegName);
			BufferedOutputStream bos = new BufferedOutputStream(fout);

			bitmap.compress(format, 100, bos);
			bos.flush();
			bos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void setCameraParameters(Camera myCamera, int type) {
		if (null != myCamera) {
			Camera.Parameters myParam = myCamera.getParameters();

			if (type == 1) {
				myParam.setPictureFormat(back_pixel_format);
				myParam.setPictureSize(back_PictureWidth,
						back_PictureHeight);
				myParam.setPreviewSize(back_PreviewWidth,
						back_PreviewHeight);
				myCamera.setDisplayOrientation(back_degrees);
				myParam.setFocusMode(back_FocusMode);
			} else {
				myParam.setPictureFormat(front_pixel_format);
				myParam.setPictureSize(front_PictureWidth, front_PictureHeight);
				myParam.setPreviewSize(front_PreviewWidth, front_PreviewHeight);
				myCamera.setDisplayOrientation(front_degrees);
				myParam.setFocusMode(front_FocusMode);
			}

			myCamera.setParameters(myParam);
		}
	}

	private void setRecordParameters(int type) {
		mediarecorder.setCamera(camera);
		mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
		if (type == 0) {
			mediarecorder.setOutputFormat(back_output_format);
			mediarecorder.setVideoEncoder(back_video_encoder);
			mediarecorder.setVideoFrameRate(back_Video_rate);
			mediarecorder.setVideoSize(back_Video_width, back_Video_height);
		} else {
			mediarecorder.setOutputFormat(front_output_format);
			mediarecorder.setVideoEncoder(front_video_encoder);
			mediarecorder.setVideoFrameRate(front_Video_rate);
			mediarecorder.setVideoSize(front_Video_width, front_Video_height);
		}
		mediarecorder.setPreviewDisplay(surfaceHolder.getSurface());
		if (front_output_format == MediaRecorder.OutputFormat.MPEG_4)
			mediarecorder.setOutputFile(DefaultVedioPath + DefaultVedioName
					+ ".mp4");
		else if (front_output_format == MediaRecorder.OutputFormat.THREE_GPP)
			mediarecorder.setOutputFile(DefaultVedioPath + DefaultVedioName
					+ ".3gp");
		else
			new Exception("不支持的生成视频格式");
	}

	/**
	 * 初始化相机參数方法(后置)
	 * 
	 * @param myCamera
	 *            Camera实例
	 * @param pixel_format
	 *            设置拍照后存储的图片格式
	 * @param PictureWidth
	 *            存储的图片像素X
	 * @param PictureHeight
	 *            存储的图片像素Y
	 * @param PreviewWidth
	 *            显示宽度X
	 * @param PreviewHeight
	 *            显示高度Y
	 * @param degrees
	 *            旋转角度
	 * @param FocusMode
	 *            调焦方式
	 */
	public static void initCameraParameters_back(int pixel_format,
			int PictureWidth, int PictureHeight, int PreviewWidth,
			int PreviewHeight, int degrees, String FocusMode) {
		MediaCamera.back_pixel_format = pixel_format;
		MediaCamera.back_PictureWidth = PictureWidth;
		MediaCamera.back_PictureHeight = PictureHeight;
		MediaCamera.back_PreviewWidth = PreviewWidth;
		MediaCamera.back_PreviewHeight = PreviewHeight;
		MediaCamera.back_degrees = degrees;
		MediaCamera.back_FocusMode = FocusMode;
	}

	/**
	 * 初始化相机參数方法(前置)
	 * 
	 * @param myCamera
	 *            Camera实例
	 * @param pixel_format
	 *            设置拍照后存储的图片格式
	 * @param PictureWidth
	 *            存储的图片像素X
	 * @param PictureHeight
	 *            存储的图片像素Y
	 * @param PreviewWidth
	 *            显示宽度X
	 * @param PreviewHeight
	 *            显示高度Y
	 * @param degrees
	 *            旋转角度
	 * @param FocusMode
	 *            调焦方式
	 */
	public static void initCameraParameters_front(int pixel_format,
			int PictureWidth, int PictureHeight, int PreviewWidth,
			int PreviewHeight, int degrees, String FocusMode) {
		MediaCamera.front_pixel_format = pixel_format;
		MediaCamera.front_PictureWidth = PictureWidth;
		MediaCamera.front_PictureHeight = PictureHeight;
		MediaCamera.front_PreviewWidth = PreviewWidth;
		MediaCamera.front_PreviewHeight = PreviewHeight;
		MediaCamera.front_degrees = degrees;
		MediaCamera.front_FocusMode = FocusMode;
	}

	/**
	 * 初始化相机摄像參数方法(后置)
	 * 
	 * @param surfaceView
	 * @param output_format
	 *            视频的封装格式MediaRecorder.OutputFormat THREE_GPP为3gp.MPEG_4为mp4
	 * @param video_encoder
	 *            视频编码MediaRecorder.VideoEncoder h263 h264
	 * @param width
	 *            分辨率width
	 * @param height
	 *            分辨率height
	 * @param rate
	 *            视频的码率
	 * @param path
	 *            文件输出的路径
	 */
	public static void initRecordParameters_back(int output_format,
			int video_encoder, int Video_width, int Video_height, int Video_rate) {
		MediaCamera.back_output_format = output_format;
		MediaCamera.back_Video_width = Video_width;
		MediaCamera.back_Video_height = Video_height;
		MediaCamera.back_output_format = output_format;
		MediaCamera.back_Video_rate = Video_rate;

	}

	/**
	 * 初始化相机摄像參数方法(前置)
	 * 
	 * @param surfaceView
	 * @param back_output_format
	 *            视频的封装格式MediaRecorder.OutputFormat THREE_GPP为3gp.MPEG_4为mp4
	 * @param back_video_encoder
	 *            视频编码MediaRecorder.VideoEncoder h263 h264
	 * @param width
	 *            分辨率width
	 * @param height
	 *            分辨率height
	 * @param rate
	 *            视频的码率
	 * @param path
	 *            文件输出的路径
	 */
	public static void initRecordParameters_front(int output_format,
			int video_encoder, int Video_width, int Video_height, int Video_rate) {
		MediaCamera.front_output_format = output_format;
		MediaCamera.front_Video_width = Video_width;
		MediaCamera.front_Video_height = Video_height;
		MediaCamera.front_output_format = output_format;
		MediaCamera.front_Video_rate = Video_rate;

	}

	/**
	 * 设置相片保存路径
	 * 
	 * @param defaultFilePath
	 *            路径 example: "/mnt/sdcard/Pictures/"
	 */
	public static void setDefaultImagePath(String defaultFilePath) {
		DefaultImagePath = defaultFilePath;
	}

	/**
	 * 设置相片名称
	 * 
	 * @param defaultFilePath
	 */
	public static void setDefaultImageName(String defaultFileName) {
		DefaultImageName = defaultFileName;
	}

	/**
	 * 设置视频保存路径
	 * 
	 * @param defaultFilePath
	 *            路径 example: "/mnt/sdcard/Pictures/"
	 */
	public static void setDefaultVedioPath(String defaultFilePath) {
		DefaultVedioPath = defaultFilePath;
	}

	/**
	 * 设置视频名称
	 * 
	 * @param defaultFilePath
	 */
	public static void setDefaultVedioName(String defaultFileName) {
		DefaultVedioName = defaultFileName;
	}

	/**
	 * 開始录像方法
	 * */
	public void startRecording() {
		camera.unlock();
		mediarecorder = new MediaRecorder();
		setRecordParameters(cameraPosition);
		try {
			mediarecorder.prepare();
			mediarecorder.start();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		isRecording = true;

	}

	/**
	 * 停止录像方法
	 * */
	public void stopRecording() {
		if (mediarecorder != null) {
			mediarecorder.stop();
			mediarecorder.release();
			mediarecorder = null;
		}
	}

	/**
	 * SurfaceHolderCallback 重写
	 * **/
	Callback surfaceHolderCallback = new Callback() {

		@Override
		public void surfaceDestroyed(SurfaceHolder arg0) {
			surfaceView = null;
			surfaceHolder = null;
			releaseCamera();
		}

		@Override
		public void surfaceCreated(SurfaceHolder arg0) {
			OpenCamera();
			camera.startPreview();
		}

		@Override
		public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
				int arg3) {
			// setCameraParameters(camera);
			camera.startPreview();

		}
	};

	private void releaseCamera() {
		if (camera != null) {
			camera.setPreviewCallback(null);
			camera.stopPreview();
			camera.release();
			camera = null;
		}
	}
}

使用时依照下面步骤调用就能够了:

1.Activity中布局SurfaceView.用于预览.
2.调用MediaCamera静态检測方法对设备检測.
3.对MediaCamera中前后置摄像头相关參数进行设定.
/* 拍照參数 */MediaCamera.setDefaultImagePath( );
MediaCamera.initCameraParameters_back( );
MediaCamera.initCameraParameters_front( );
/* 摄像參数 */
MediaCamera.setDefaultVedioPath( );
MediaCamera.initRecordParameters_back( );
MediaCamera.initRecordParameters_front( );
4. new MediaCamera()传入SurfaceView.
5. takePhoto()拍照
6. startRecording();
stopRecording();
可通过isRecording标记推断拍摄是否完毕


资源已上传CSDN 地址:点此下载


欢迎拍砖指点,转载请注明出处,谢谢

posted @ 2014-07-09 15:55  mengfanrong  阅读(523)  评论(0编辑  收藏  举报