将camera肯定是要有预览界面来配合着才有激情,不然无图无真相。那就讲的没有太大的激情。
我们对camera的使用一般是在app里面有用到设置获取图片的时候提供一个拍照功能,一般是跳转到系统的拍照界面使用camera来获取图片;有的app有需求就跳转到自己的拍照界面。我们知道系统的应用其实也是个app,无论是跳转到系统拍照界面还是自己的拍照界面其实都是一个preview,然后再“截屏”生成一个图片。我下面讲一些关于camera的基础和preview的结合使用。
首先要获取camera的属性:Camera.Parameters parameters = camera.getParameters();
camera的基本属性设置:
(1)设置预览大小 :
parameters.setPreviewSize(“宽”, “高”);
一般设置的预览大小就是手机屏幕的宽高,那么就要获取屏幕的宽高,然后再经过稍微的处理:
WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);Display display = manager.getDefaultDisplay();宽:display.getWidth() 高:display.getHeight() 由于下面的介绍都会用到一个系统的实体Point,所以我这里把宽高设置到这个实体里面,然后方便使用,然后就得到下面的代码:
WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);Display display = manager.getDefaultDisplay();//获取屏幕的宽高(像素值)设置到一个实体(point)里面Point screenResolution = new Point(display.getWidth(), display.getHeight());然后再根据屏幕的宽高做优化处理:
/*根据相机的参数和手机屏幕参数来重新设置相机的*/public Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {String previewSizeValueString = parameters.get("preview-size-values");if (previewSizeValueString == null) {previewSizeValueString = parameters.get("preview-size-value");}Point cameraResolution = null;if (previewSizeValueString != null) {cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);}if (cameraResolution == null) {//没有找到最优的预览效果,那么至少也要确保相机分辨率是8的倍数(我也不知道为什么),下面的操作就是防备屏幕不是8的倍数,如果//是8的倍数,就会在上面的寻找最优size的时候会找到的cameraResolution = new Point((screenResolution.x >> 3) << 3,(screenResolution.y >> 3) << 3);}return cameraResolution;}/*根据预览大小和手机屏幕大小来设一个比较完美的预览效果*/public Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {int bestX = 0;int bestY = 0;int diff = Integer.MAX_VALUE;//差值for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {previewSize = previewSize.trim();int dimPosition = previewSize.indexOf('x');if (dimPosition < 0) {//这是一个很差的预览大小continue;}int newX;int newY;try {newX = Integer.parseInt(previewSize.substring(0, dimPosition));newY = Integer.parseInt(previewSize.substring(dimPosition + 1));} catch (NumberFormatException nfe) {//字符串转换异常,这是自己写的tryCatch,是为了安全起见continue;}int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);if (newDiff == 0) {bestX = newX;bestY = newY;break;} else if (newDiff < diff) {bestX = newX;bestY = newY;diff = newDiff;}}if (bestY > 0 && bestX > 0) {return new Point(bestX, bestY);}return null;}
最后把优化处理之后的point的数据设置个camera的parameters:
Camera.Parameters parameters = camera.getParameters();parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);//设置相机的预览size
(2)设置闪光灯:
/*设置闪光灯,本来是不用设置的,应该是直接获取,但是根据三星建议说防止黑客攻击,最好设置一下*/private void setFlash(Camera.Parameters parameters) {if (Build.MODEL.contains("Behold II") && Integer.parseInt(Build.VERSION.SDK) == 3) {parameters.set("flash-value", 1);} else {parameters.set("flash-value", 2);}parameters.set("flash-mode", "off");}
(3)设置缩放:
一般使用camera进行拍照和录制视频的时候都要支持手势识别进行缩放,原理就是把手势缩放的xy值然后进行算法转换然后动态的设置到camera的parameter上。
/*设置缩放*/private void setZoom(Camera.Parameters parameters) {String zoomSupportString = parameters.get("zoom-supported");if (zoomSupportString != null && !Boolean.parseBoolean(zoomSupportString)) {return;}int tenDesiredZoom = TEN_DESIRED_ZOOM;//TEN_DESIRED_ZOOM = 27String maxZoomString = parameters.get("max-zoom");if (maxZoomString != null) {try {int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));if (tenDesiredZoom > tenMaxZoom) {tenDesiredZoom = tenMaxZoom;}} catch (NumberFormatException e) {Log.i(TAG, "获取原本的缩放最大级别转换失败");}String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");if (takingPictureZoomMaxString != null) {try {int takePicMax = Integer.parseInt(takingPictureZoomMaxString);if (tenDesiredZoom > takePicMax) {tenDesiredZoom = takePicMax;}Log.i(TAG, "拍照缩放级别被最原始级别小");} catch (NumberFormatException nfe) {Log.i(TAG, "拍照缩放级别转换失败");}}String motZoomMaxString = parameters.get("mot-zoom-values");if (motZoomMaxString != null) {tenDesiredZoom = findBestMotZoomValue(motZoomMaxString, tenDesiredZoom);}String motZoomStepString = parameters.get("mot-zoom-step");if (motZoomStepString != null) {try {double motZoomStep = Double.parseDouble(motZoomStepString.trim());int tenZoomStep = (int) (10.0 * motZoomStep);if (tenZoomStep > 1) {tenDesiredZoom -= tenDesiredZoom % tenZoomStep;}} catch (NumberFormatException nfe) {}}if (maxZoomString != null || motZoomMaxString != null) {parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));}if (takingPictureZoomMaxString != null) {parameters.set("taking-picture-zoom", tenDesiredZoom);}}}private static int findBestMotZoomValue(CharSequence stringValues, int tenDesireZoom) {int tenBestValue = 0;for (String stringValue : COMMA_PATTERN.split(stringValues)) {stringValue = stringValue.trim();double value;try {value = Double.parseDouble(stringValue);} catch (NumberFormatException nfe) {return tenDesireZoom;}int tenValue = (int) (10.0 * value);if (Math.abs(tenDesireZoom - value) < Math.abs(tenDesireZoom - tenBestValue)) {tenBestValue = tenValue;}}return tenBestValue;}使用的时候你可以直接进行设置,parameter.set("zoom","10");来设置缩放。
最后贴一个完整测camera的配置类:
import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;import java.lang.reflect.Method;
import java.util.regex.Pattern;public class CameraConfigurationManager {private static final String TAG = "Cy==CameraConfigManager";private Context mContext;private Point screenResolution;private static final Pattern COMMA_PATTERN = Pattern.compile(",");private Point cameraResolution;private static final int TEN_DESIRED_ZOOM = 27;//设置十级缩放级别private int previewFormat;private String previewFormatString;private CameraConfigurationManager() {}public Point getCameraResolution() {return cameraResolution;}public Point getScreenResolution() {return screenResolution;}public int getPreviewFormat() {return previewFormat;}public String getPreviewFormatString() {return previewFormatString;}private static final class Holder {private static final CameraConfigurationManager CAMERA_CONFIGURATION_MANAGER = new CameraConfigurationManager();}public static CameraConfigurationManager getInstance() {return Holder.CAMERA_CONFIGURATION_MANAGER;}public CameraConfigurationManager setContext(Context mContext) {this.mContext = mContext;return this;}/*获取手机的相机和手机屏幕的一些基本参数*/public void getCameraParams(Camera camera) {Camera.Parameters parameters = camera.getParameters();//获取相机预览界面格式previewFormat = parameters.getPreviewFormat();previewFormatString = parameters.get("preview-format");WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);Display display = manager.getDefaultDisplay();//获取屏幕的宽高(像素值)设置到一个实体(point)里面screenResolution = new Point(display.getWidth(), display.getHeight());//尽量获取相机最好的pointcameraResolution = getCameraResolution(parameters, screenResolution);}/*设置相机的预览参数(渴望设置成什么样就设置成什么样)*/public void setDseiredCameraParameters(Camera camera) {Camera.Parameters parameters = camera.getParameters();parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);//设置相机的预览sizesetFlash(parameters);setZoom(parameters);setDisplayOrientation(camera, 90);camera.setParameters(parameters);}/*设置展示角度*/private void setDisplayOrientation(Camera camera, int orientation) {Class<? extends Camera> clazz = camera.getClass();try {Method displayOrientation = clazz.getMethod("setDisplayOrientation", new Class[]{int.class});if (displayOrientation != null) {displayOrientation.invoke(camera, new Object[]{orientation});}} catch (Exception e) {e.printStackTrace();}}/*设置缩放*/private void setZoom(Camera.Parameters parameters) {String zoomSupportString = parameters.get("zoom-supported");if (zoomSupportString != null && !Boolean.parseBoolean(zoomSupportString)) {return;}int tenDesiredZoom = TEN_DESIRED_ZOOM;//TEN_DESIRED_ZOOM = 27String maxZoomString = parameters.get("max-zoom");if (maxZoomString != null) {try {int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));if (tenDesiredZoom > tenMaxZoom) {tenDesiredZoom = tenMaxZoom;}} catch (NumberFormatException e) {Log.i(TAG, "获取原本的缩放最大级别转换失败");}String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");if (takingPictureZoomMaxString != null) {try {int takePicMax = Integer.parseInt(takingPictureZoomMaxString);if (tenDesiredZoom > takePicMax) {tenDesiredZoom = takePicMax;}Log.i(TAG, "拍照缩放级别被最原始级别小");} catch (NumberFormatException nfe) {Log.i(TAG, "拍照缩放级别转换失败");}}String motZoomMaxString = parameters.get("mot-zoom-values");if (motZoomMaxString != null) {tenDesiredZoom = findBestMotZoomValue(motZoomMaxString, tenDesiredZoom);}String motZoomStepString = parameters.get("mot-zoom-step");if (motZoomStepString != null) {try {double motZoomStep = Double.parseDouble(motZoomStepString.trim());int tenZoomStep = (int) (10.0 * motZoomStep);if (tenZoomStep > 1) {tenDesiredZoom -= tenDesiredZoom % tenZoomStep;}} catch (NumberFormatException nfe) {}}if (maxZoomString != null || motZoomMaxString != null) {parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));}if (takingPictureZoomMaxString != null) {parameters.set("taking-picture-zoom", tenDesiredZoom);}}}private static int findBestMotZoomValue(CharSequence stringValues, int tenDesireZoom) {int tenBestValue = 0;for (String stringValue : COMMA_PATTERN.split(stringValues)) {stringValue = stringValue.trim();double value;try {value = Double.parseDouble(stringValue);} catch (NumberFormatException nfe) {return tenDesireZoom;}int tenValue = (int) (10.0 * value);if (Math.abs(tenDesireZoom - value) < Math.abs(tenDesireZoom - tenBestValue)) {tenBestValue = tenValue;}}return tenBestValue;}/*设置闪光灯,本来是不用设置的,应该是直接获取,但是根据三星建议说防止黑客攻击,最好设置一下*/private void setFlash(Camera.Parameters parameters) {if (Build.MODEL.contains("Behold II") && CameraManager.SDK_INT == 3) {parameters.set("flash-value", 1);} else {parameters.set("flash-value", 2);}parameters.set("flash-mode", "off");}/*根据相机的参数和手机屏幕参数来重新设置相机的*/public Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {String previewSizeValueString = parameters.get("preview-size-values");if (previewSizeValueString == null) {previewSizeValueString = parameters.get("preview-size-value");}Point cameraResolution = null;if (previewSizeValueString != null) {cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);}if (cameraResolution == null) {//没有找到最优的预览效果,那么至少也要确保相机分辨率是8的倍数(我也不知道为什么),下面的操作就是防备屏幕不是8的倍数,如果//是8的倍数,就会在上面的寻找最优size的时候会找到的cameraResolution = new Point((screenResolution.x >> 3) << 3,(screenResolution.y >> 3) << 3);}return cameraResolution;}/*根据预览大小和手机屏幕大小来设一个比较完美的预览效果*/public Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {int bestX = 0;int bestY = 0;int diff = Integer.MAX_VALUE;//差值for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {previewSize = previewSize.trim();int dimPosition = previewSize.indexOf('x');if (dimPosition < 0) {//这是一个很差的预览大小continue;}int newX;int newY;try {newX = Integer.parseInt(previewSize.substring(0, dimPosition));newY = Integer.parseInt(previewSize.substring(dimPosition + 1));} catch (NumberFormatException nfe) {//字符串转换异常,这是自己写的tryCatch,是为了安全起见continue;}int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);if (newDiff == 0) {bestX = newX;bestY = newY;break;} else if (newDiff < diff) {bestX = newX;bestY = newY;diff = newDiff;}}if (bestY > 0 && bestX > 0) {return new Point(bestX, bestY);}return null;}
}