Camera API 介绍系列文章:
Android Camera之 --- Camera API说明(一)
Android Camera之 --- Camera API说明(二)
Android Camera之 --- Camera API说明(三)
推荐大家浏览Android源码最便利的方法:
http://androidxref.com/
从Android5.0开始google引入新的Camera API,位于:http://androidxref.com/5.0.0_r2/xref/frameworks/base/core/java/android/hardware/camera2/
后续我会写几篇关于Camera2 API的分析文章。
Android Camera API说明:
Camera API基本上有三大功能,预览;拍照;录像,所有对Camera API的调用基本上就是围绕这三种功能来进行的。
Android Camera API 实现位于/frameworks/base/core/java/android/hardware/Camera.java
首先,在开发Camera相关APP时需要在AndroidManifest.xml中申请camera使用权限以及其他有关camera的feature,如:
uses-permission android:name="android.permission.CAMERA" uses-feature android:name="android.hardware.camera" uses-feature android:name="android.hardware.camera.autofocus"
预览操作:
1. 通过调用open()或者open(int cameraId)来获取Camera实例;
2. 通过调用getParameters()来获取camera默认的参数集;
3. 根据需要通过Parameters封装的函数来更改必要的参数;
4. 设置参数调用setParameters(Camera.Parameters);
5. 必须调用setPreviewDisplay(SurfaceHolder)来设置预览图像的显示,若没有Surface,camera不能开始预览;
6. 调用startPreview()来开始预览;
7. 想要停止预览则调用stopPreview();
拍照操作:
1. 确保camera已经在预览模式;
2. 调用takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback)来拍照;
3. 等待takePicture()函数设置的callback返回图片数据;
4. 当takePicture()函数被调用后,预览画面就会停止,想要继续预览或者拍照,则必须调用startPreview()开始预览;
视频录制操作:
1. 确保Camera已经在预览模式;
2. 调用unlock()通知cameraserver允许mediaserver进程访问Camera;
3. 调用MediaRecorder初始化MediaRecorder实例并设置相应的音频视频参数;
4. 调用MediaRecorder.setCamera(Camera)接口将此camera实例做为video datasource;
5. 调用MediaRecorder相关的函数进行视频录制;
6. 结束视频录制也是由MediaRecorder相关的函数来控制;
7. 调用reconnect()接口来对camera实例重新上锁;
介绍完大致的操作步骤后首先对Camera的内部类进行说明:
public static class CameraInfo { public static final int CAMERA_FACING_BACK = 0; // 在屏幕的相反侧,也就是代表后置摄像头 public static final int CAMERA_FACING_FRONT = 1; // 在屏幕的同侧,代表前置摄像头 public int facing; // 上面定义的两选其一,代表次摄像头的相对位置 public int orientation; // 相机的转角,一般有0,90,180,270. public boolean canDisableShutterSound; // 是否支持拍照关闭声音 };
若要想Camera参数设置生效,则必须调用Camera.setParameters(Camera.Parameters)接口来设置修改后的Camera参数集。例如:
当调用Camera.Parameters.setWhiteBalance()时,并不能让WB生效,必须通过调用Camera.setParameters(Camera.Parameters)来让修改后的参数集设置生效;不同的硬件有不同的参数功能,比如所支持的preview size和flash mode都是有所不同的,使用者必须首先获取所支持的参数信息,进一步根据所支持的信息来设置相应的参数。下面介绍camera的参数集Camera.Parameters内部类:
@Deprecated public class Parameters { // 从下面的定义可以看出每一个参数都是通过key-value来存储的,代表了camera硬件设备的特性和性能,也有一部分是作为设置参数存在的 // Parameter keys to communicate with the camera driver. // 预览画面大小,一般有默认值,可以通过调用getPreviewSize()来获取默认值, // 使用者调用getSupportedPreviewSizes()获取所支持的preview size,进而调用setPreviewSize(int width, int height)来设置预览大小; private static final String KEY_PREVIEW_SIZE = "preview-size"; // previewCallback()返回数据格式,可以通过调用getPreviewFormat()来获取默认值, // 使用者调用getSupportedPreviewFormats()获取所支持的颜色格式,进而调用setPreviewFormat(int pixel_format)来设置callback数据格式; private static final String KEY_PREVIEW_FORMAT = "preview-format"; // 预览帧率,使用者调用getPreviewFrameRate()来获取默认的预览帧率, // 使用者可以通过getSupportedPreviewFrameRates()来获取所支持的预览帧率,进而调用 private static final String KEY_PREVIEW_FRAME_RATE = "preview-frame-rate"; // 用来替代KEY_PREVIEW_FRAME_RATE而设置的,因为camera设备的帧率是不固定的,根据光照条件的差异,曝光时间是不同的,若想得到较好的图像质量, // 则必须牺牲帧率,所以此处的预览帧率是一个范围,有最大值和最小值之分,可以通过getPreviewFpsRange(int[] range)来获取默认值, // getSupportedPreviewFpsRange()来获取所支持的预览帧率范围,进而通过setPreviewFpsRange(int min, int max)来设置预览帧率范围, private static final String KEY_PREVIEW_FPS_RANGE = "preview-fps-range"; // 拍照图片大小,可以通过getPictureSize()来获取默认值, // 使用者getSupportedPictureSizes()来获取所支持的拍照图片大小,进而通过setPictureSize(int width, int height)来设置拍照图片大小 private static final String KEY_PICTURE_SIZE = "picture-size"; // 拍照图像格式,可以通过getPictureFormat()来获取默认的拍照图片格式, // 使用者通过getSupportedPictureFormats()来获取所支持的拍照图片格式,进而通过setPictureFormat(int pixel_format)来设置拍照图片格式 private static final String KEY_PICTURE_FORMAT = "picture-format"; // 获取所支持的拍照Thumbnail大小,分别为width和height private static final String KEY_JPEG_THUMBNAIL_SIZE = "jpeg-thumbnail-size"; // 拍照Thumbnail宽度,通过getJpegThumbnailSize()获取,通过setJpegThumbnailSize(int width, int height)来设置 private static final String KEY_JPEG_THUMBNAIL_WIDTH = "jpeg-thumbnail-width"; // 拍照Thumbnail高度,通过getJpegThumbnailSize()获取,通过setJpegThumbnailSize(int width, int height)来设置 private static final String KEY_JPEG_THUMBNAIL_HEIGHT = "jpeg-thumbnail-height"; // EXIF Thumbnail 图像质量级别[0~100], 100为最佳图像质量, // 可通过getJpegThumbnailQuality()和setJpegThumbnailQuality(int quality)来获取和设置Thumbnail图像的质量; private static final String KEY_JPEG_THUMBNAIL_QUALITY = "jpeg-thumbnail-quality"; // 拍照图片JPEG图像质量, 通过setJpegQuality(int quality)和getJpegQuality()来设置或获取图片质量 private static final String KEY_JPEG_QUALITY = "jpeg-quality"; // 设置图像旋转角度,0,90,180,270. private static final String KEY_ROTATION = "rotation"; // GPS纬度信息,用于拍照 private static final String KEY_GPS_LATITUDE = "gps-latitude"; // GPS经度信息,用于拍照 private static final String KEY_GPS_LONGITUDE = "gps-longitude"; // GPS海拔信息,用于拍照 private static final String KEY_GPS_ALTITUDE = "gps-altitude"; // GPS时间信息,用于拍照 private static final String KEY_GPS_TIMESTAMP = "gps-timestamp"; // GPS信息处理方式,用于拍照 private static final String KEY_GPS_PROCESSING_METHOD = "gps-processing-method"; // 相机WB模式,可通过getSupportedWhiteBalance()来获取所支持的模式, // 模式有:AUTO,INCANDESCENT,FLUORESCENT,WARM_FLUORESCENT,DAYLIGHT,CLOUDY_DAYLIGHT,TWILIGHT,SHADE, // 通过String getWhiteBalance()和setWhiteBalance(String value)来获取或设置WB模式 private static final String KEY_WHITE_BALANCE = "whitebalance"; // 预览色彩效果,可通过getSupportedColorEffects()获取所支持的色彩效果, // 色彩效果有NONE,MONO,NEGATIVE,SOLARIZE,SEPIA,POSTERIZE,WHITEBOARD,BLACKBOARD,AQUA, // 通过getColorEffect()和setColorEffect(String value)来获取和设置色彩效果 private static final String KEY_EFFECT = "effect"; // antibanding 模式, 可以通过getSupportedAntibanding()来获取所支持的antibanding, // Antibanding模式有:AUTO,50HZ,60HZ,OFF // 可以通过getAntibanding()和setAntibanding(String antibanding)来获取或者设置Antibanding模式, private static final String KEY_ANTIBANDING = "antibanding"; // 场景模式,可以通过getSupportedSceneModes()来获取所支持的场景模式 // 场景模式有: AUTO,ACTION,PORTRAIT,LANDSCAPE,NIGHT,NIGHT_PORTRAIT, // THEATRE,BEACH,SNOW,SUNSET,STEADYPHOTO,FIREWORKS,SPORTS,PARTY, // CANDLELIGHT, BARCODE // 可以通过getSceneMode()和setSceneMode(String value)来获取或设置场景模式, private static final String KEY_SCENE_MODE = "scene-mode"; // 闪光灯模式,可以通过getSupportedFlashModes()来获取所支持的闪光灯模式 // 闪光灯模式: OFF,AUTO,ON,RED_EYE,TORCH // 可以通过getFlashMode()和setFlashMode(String value)来获取或设置闪光灯模式, private static final String KEY_FLASH_MODE = "flash-mode"; // 拍照对焦模式, 可以通过getSupportedFocusModes()来获取所支持的对焦模式, // 对焦模式有:AUTO,INFINITY,MACRO,FIXED,EDOF,CONTINUOUS_VIDEO // 可以通过getFocusMode()和setFocusMode(String value)来获取或设置对焦模式, private static final String KEY_FOCUS_MODE = "focus-mode"; // 对焦区域, getFocusAreas()和setFocusAreas(List<Area> focusAreas)用来获取或设置对焦区域 private static final String KEY_FOCUS_AREAS = "focus-areas"; // 对焦区域的最大个数 private static final String KEY_MAX_NUM_FOCUS_AREAS = "max-num-focus-areas"; // 焦距, 可以调用getFocalLength()来获取焦距长度 private static final String KEY_FOCAL_LENGTH = "focal-length"; // 水平视角,通过getHorizontalViewAngle()获取 private static final String KEY_HORIZONTAL_VIEW_ANGLE = "horizontal-view-angle"; // 垂直视角, 通过getVerticalViewAngle()获取 private static final String KEY_VERTICAL_VIEW_ANGLE = "vertical-view-angle"; // 曝光补偿, 通过getExposureCompensation()和setExposureCompensation(int value)获取或设置曝光补偿序号, private static final String KEY_EXPOSURE_COMPENSATION = "exposure-compensation"; // 最大曝光补偿序号, 通过getMaxExposureCompensation()获取, private static final String KEY_MAX_EXPOSURE_COMPENSATION = "max-exposure-compensation"; // 最小曝光补偿序号,通过getMinExposureCompensation()获取, private static final String KEY_MIN_EXPOSURE_COMPENSATION = "min-exposure-compensation"; // 曝光补偿步长,通过getExposureCompensationStep()获取, private static final String KEY_EXPOSURE_COMPENSATION_STEP = "exposure-compensation-step"; // 自动曝光锁定,通过setAutoExposureLock(boolean toggle)和getAutoExposureLock()来设定或获取自动曝光锁定状态, private static final String KEY_AUTO_EXPOSURE_LOCK = "auto-exposure-lock"; // 自动曝光锁定是否支持,通过isAutoExposureLockSupported()判定是否支持自动曝光锁定设置, private static final String KEY_AUTO_EXPOSURE_LOCK_SUPPORTED = "auto-exposure-lock-supported"; // 自动白平衡锁定, 通过setAutoWhiteBalanceLock(boolean toggle)和getAutoWhiteBalanceLock()来设置或获取自动白平衡锁定状态, private static final String KEY_AUTO_WHITEBALANCE_LOCK = "auto-whitebalance-lock"; // 自动白平衡锁定是否支持,通过isAutoWhiteBalanceLockSupported()判定是否支持自动白平衡锁定设置, private static final String KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED = "auto-whitebalance-lock-supported"; // 曝光区域,通过getMeteringAreas()和setMeteringAreas(List<Area> meteringAreas)来获取或设置曝光区域, private static final String KEY_METERING_AREAS = "metering-areas"; // 曝光区域的最大个数,通过getMaxNumMeteringAreas()来获取 private static final String KEY_MAX_NUM_METERING_AREAS = "max-num-metering-areas"; // 图像缩放,通过getZoom()和setZoom(int value)来获取或设定缩放值 private static final String KEY_ZOOM = "zoom"; // 最大缩放值,通过getMaxZoom()来获取 private static final String KEY_MAX_ZOOM = "max-zoom"; // 缩放比,需要除以100,来表示,3.2x--->320, 第一个值为100, 最后一个为最大缩放比 private static final String KEY_ZOOM_RATIOS = "zoom-ratios"; // 缩放是否支持,通过isZoomSupported()来判定 private static final String KEY_ZOOM_SUPPORTED = "zoom-supported"; // 平滑缩放是否支持,通过isSmoothZoomSupported()来判定 private static final String KEY_SMOOTH_ZOOM_SUPPORTED = "smooth-zoom-supported"; // 像距,对焦时物体到焦点的距离 private static final String KEY_FOCUS_DISTANCES = "focus-distances"; // 获取录像所需的图像大小,通过getSupportedVideoSizes()来获取 private static final String KEY_VIDEO_SIZE = "video-size"; // 获取被推荐的预览图像大小,通过getPreferredPreviewSizeForVideo()获取 private static final String KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO = "preferred-preview-size-for-video"; // 硬件加速人脸识别的支持的最大个数,通过getMaxNumDetectedFaces()来获取 private static final String KEY_MAX_NUM_DETECTED_FACES_HW = "max-num-detected-faces-hw"; // 软件人脸识别的支持的最大个数 private static final String KEY_MAX_NUM_DETECTED_FACES_SW = "max-num-detected-faces-sw"; // 暗示将会开启视频录制,而不是照相,通过setRecordingHint(boolean hint)来设置 private static final String KEY_RECORDING_HINT = "recording-hint"; // 视频录制时是否支持快照,通过isVideoSnapshotSupported()来获取值 private static final String KEY_VIDEO_SNAPSHOT_SUPPORTED = "video-snapshot-supported"; // 在相机预览或视频录制时开启或关闭抖动抑制,不能在拍照时抑制运动模糊 private static final String KEY_VIDEO_STABILIZATION = "video-stabilization"; // 视频稳定特性是否支持,通过isVideoStabilizationSupported()来获取 private static final String KEY_VIDEO_STABILIZATION_SUPPORTED = "video-stabilization-supported"; // Parameter key suffix for supported values. private static final String SUPPORTED_VALUES_SUFFIX = "-values"; private static final String TRUE = "true"; private static final String FALSE = "false"; // Values for white balance settings. public static final String WHITE_BALANCE_AUTO = "auto"; public static final String WHITE_BALANCE_INCANDESCENT = "incandescent"; public static final String WHITE_BALANCE_FLUORESCENT = "fluorescent"; public static final String WHITE_BALANCE_WARM_FLUORESCENT = "warm-fluorescent"; public static final String WHITE_BALANCE_DAYLIGHT = "daylight"; public static final String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight"; public static final String WHITE_BALANCE_TWILIGHT = "twilight"; public static final String WHITE_BALANCE_SHADE = "shade"; // Values for color effect settings. public static final String EFFECT_NONE = "none"; public static final String EFFECT_MONO = "mono"; public static final String EFFECT_NEGATIVE = "negative"; public static final String EFFECT_SOLARIZE = "solarize"; public static final String EFFECT_SEPIA = "sepia"; public static final String EFFECT_POSTERIZE = "posterize"; public static final String EFFECT_WHITEBOARD = "whiteboard"; public static final String EFFECT_BLACKBOARD = "blackboard"; public static final String EFFECT_AQUA = "aqua"; // Values for antibanding settings. public static final String ANTIBANDING_AUTO = "auto"; public static final String ANTIBANDING_50HZ = "50hz"; public static final String ANTIBANDING_60HZ = "60hz"; public static final String ANTIBANDING_OFF = "off"; // Values for flash mode settings. /** * Flash will not be fired. */ public static final String FLASH_MODE_OFF = "off"; /** * Flash will be fired automatically when required. The flash may be fired * during preview, auto-focus, or snapshot depending on the driver. */ public static final String FLASH_MODE_AUTO = "auto"; /** * Flash will always be fired during snapshot. The flash may also be * fired during preview or auto-focus depending on the driver. */ public static final String FLASH_MODE_ON = "on"; /** * Flash will be fired in red-eye reduction mode. */ public static final String FLASH_MODE_RED_EYE = "red-eye"; /** * Constant emission of light during preview, auto-focus and snapshot. * This can also be used for video recording. */ public static final String FLASH_MODE_TORCH = "torch"; /** * Scene mode is off. */ public static final String SCENE_MODE_AUTO = "auto"; /** * Take photos of fast moving objects. Same as {@link * #SCENE_MODE_SPORTS}. */ public static final String SCENE_MODE_ACTION = "action"; /** * Take people pictures. */ public static final String SCENE_MODE_PORTRAIT = "portrait"; /** * Take pictures on distant objects. */ public static final String SCENE_MODE_LANDSCAPE = "landscape"; /** * Take photos at night. */ public static final String SCENE_MODE_NIGHT = "night"; /** * Take people pictures at night. */ public static final String SCENE_MODE_NIGHT_PORTRAIT = "night-portrait"; /** * Take photos in a theater. Flash light is off. */ public static final String SCENE_MODE_THEATRE = "theatre"; /** * Take pictures on the beach. */ public static final String SCENE_MODE_BEACH = "beach"; /** * Take pictures on the snow. */ public static final String SCENE_MODE_SNOW = "snow"; /** * Take sunset photos. */ public static final String SCENE_MODE_SUNSET = "sunset"; /** * Avoid blurry pictures (for example, due to hand shake). */ public static final String SCENE_MODE_STEADYPHOTO = "steadyphoto"; /** * For shooting firework displays. */ public static final String SCENE_MODE_FIREWORKS = "fireworks"; /** * Take photos of fast moving objects. Same as {@link * #SCENE_MODE_ACTION}. */ public static final String SCENE_MODE_SPORTS = "sports"; /** * Take indoor low-light shot. */ public static final String SCENE_MODE_PARTY = "party"; /** * Capture the naturally warm color of scenes lit by candles. */ public static final String SCENE_MODE_CANDLELIGHT = "candlelight"; /** * Applications are looking for a barcode. Camera driver will be * optimized for barcode reading. */ public static final String SCENE_MODE_BARCODE = "barcode"; /** * Capture a scene using high dynamic range imaging techniques. The * camera will return an image that has an extended dynamic range * compared to a regular capture. Capturing such an image may take * longer than a regular capture. */ public static final String SCENE_MODE_HDR = "hdr"; /** * Auto-focus mode. Applications should call {@link * #autoFocus(AutoFocusCallback)} to start the focus in this mode. */ public static final String FOCUS_MODE_AUTO = "auto"; /** * Focus is set at infinity. Applications should not call * {@link #autoFocus(AutoFocusCallback)} in this mode. */ public static final String FOCUS_MODE_INFINITY = "infinity"; /** * Macro (close-up) focus mode. Applications should call * {@link #autoFocus(AutoFocusCallback)} to start the focus in this * mode. */ public static final String FOCUS_MODE_MACRO = "macro"; /** * Focus is fixed. The camera is always in this mode if the focus is not * adjustable. If the camera has auto-focus, this mode can fix the * focus, which is usually at hyperfocal distance. Applications should * not call {@link #autoFocus(AutoFocusCallback)} in this mode. */ public static final String FOCUS_MODE_FIXED = "fixed"; /** * Extended depth of field (EDOF). Focusing is done digitally and * continuously. Applications should not call {@link * #autoFocus(AutoFocusCallback)} in this mode. */ public static final String FOCUS_MODE_EDOF = "edof"; /** * Continuous auto focus mode intended for video recording. The camera * continuously tries to focus. This is the best choice for video * recording because the focus changes smoothly . Applications still can * call {@link #takePicture(Camera.ShutterCallback, * Camera.PictureCallback, Camera.PictureCallback)} in this mode but the * subject may not be in focus. Auto focus starts when the parameter is * set. * * <p>Since API level 14, applications can call {@link * #autoFocus(AutoFocusCallback)} in this mode. The focus callback will * immediately return with a boolean that indicates whether the focus is * sharp or not. The focus position is locked after autoFocus call. If * applications want to resume the continuous focus, cancelAutoFocus * must be called. Restarting the preview will not resume the continuous * autofocus. To stop continuous focus, applications should change the * focus mode to other modes. * * @see #FOCUS_MODE_CONTINUOUS_PICTURE */ public static final String FOCUS_MODE_CONTINUOUS_VIDEO = "continuous-video"; /** * Continuous auto focus mode intended for taking pictures. The camera * continuously tries to focus. The speed of focus change is more * aggressive than {@link #FOCUS_MODE_CONTINUOUS_VIDEO}. Auto focus * starts when the parameter is set. * * <p>Applications can call {@link #autoFocus(AutoFocusCallback)} in * this mode. If the autofocus is in the middle of scanning, the focus * callback will return when it completes. If the autofocus is not * scanning, the focus callback will immediately return with a boolean * that indicates whether the focus is sharp or not. The apps can then * decide if they want to take a picture immediately or to change the * focus mode to auto, and run a full autofocus cycle. The focus * position is locked after autoFocus call. If applications want to * resume the continuous focus, cancelAutoFocus must be called. * Restarting the preview will not resume the continuous autofocus. To * stop continuous focus, applications should change the focus mode to * other modes. * * @see #FOCUS_MODE_CONTINUOUS_VIDEO */ public static final String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture"; // Indices for focus distance array. /** * The array index of near focus distance for use with * {@link #getFocusDistances(float[])}. */ public static final int FOCUS_DISTANCE_NEAR_INDEX = 0; /** * The array index of optimal focus distance for use with * {@link #getFocusDistances(float[])}. */ public static final int FOCUS_DISTANCE_OPTIMAL_INDEX = 1; /** * The array index of far focus distance for use with * {@link #getFocusDistances(float[])}. */ public static final int FOCUS_DISTANCE_FAR_INDEX = 2; /** * The array index of minimum preview fps for use with {@link * #getPreviewFpsRange(int[])} or {@link * #getSupportedPreviewFpsRange()}. */ public static final int PREVIEW_FPS_MIN_INDEX = 0; /** * The array index of maximum preview fps for use with {@link * #getPreviewFpsRange(int[])} or {@link * #getSupportedPreviewFpsRange()}. */ public static final int PREVIEW_FPS_MAX_INDEX = 1; // Formats for setPreviewFormat and setPictureFormat. private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp"; private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp"; private static final String PIXEL_FORMAT_YUV422I = "yuv422i-yuyv"; private static final String PIXEL_FORMAT_YUV420P = "yuv420p"; private static final String PIXEL_FORMAT_RGB565 = "rgb565"; private static final String PIXEL_FORMAT_JPEG = "jpeg"; private static final String PIXEL_FORMAT_BAYER_RGGB = "bayer-rggb"; /** * Order matters: Keys that are {@link #set(String, String) set} later * will take precedence over keys that are set earlier (if the two keys * conflict with each other). * * <p>One example is {@link #setPreviewFpsRange(int, int)} , since it * conflicts with {@link #setPreviewFrameRate(int)} whichever key is set later * is the one that will take precedence. * </p> */ private final LinkedHashMap<String, String> mMap; private Parameters() { mMap = new LinkedHashMap<String, String>(/*initialCapacity*/64); } /** * Overwrite existing parameters with a copy of the ones from {@code other}. * * <b>For use by the legacy shim only.</b> * * @hide */ public void copyFrom(Parameters other) { if (other == null) { throw new NullPointerException("other must not be null"); } mMap.putAll(other.mMap); } private Camera getOuter() { return Camera.this; } /** * Value equality check. * * @hide */ public boolean same(Parameters other) { if (this == other) { return true; } return other != null && Parameters.this.mMap.equals(other.mMap); } /** * Writes the current Parameters to the log. * @hide * @deprecated */ @Deprecated public void dump() { Log.e(TAG, "dump: size=" + mMap.size()); for (String k : mMap.keySet()) { Log.e(TAG, "dump: " + k + "=" + mMap.get(k)); } } /** * Creates a single string with all the parameters set in * this Parameters object. * <p>The {@link #unflatten(String)} method does the reverse.</p> * * @return a String with all values from this Parameters object, in * semi-colon delimited key-value pairs */ public String flatten() { StringBuilder flattened = new StringBuilder(128); for (String k : mMap.keySet()) { flattened.append(k); flattened.append("="); flattened.append(mMap.get(k)); flattened.append(";"); } // chop off the extra semicolon at the end flattened.deleteCharAt(flattened.length()-1); return flattened.toString(); } /** * Takes a flattened string of parameters and adds each one to * this Parameters object. * <p>The {@link #flatten()} method does the reverse.</p> * * @param flattened a String of parameters (key-value paired) that * are semi-colon delimited */ public void unflatten(String flattened) { mMap.clear(); TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(';'); splitter.setString(flattened); for (String kv : splitter) { int pos = kv.indexOf('='); if (pos == -1) { continue; } String k = kv.substring(0, pos); String v = kv.substring(pos + 1); mMap.put(k, v); } } public void remove(String key) { mMap.remove(key); } /** * Sets a String parameter. * * @param key the key name for the parameter * @param value the String value of the parameter */ public void set(String key, String value) { if (key.indexOf('=') != -1 || key.indexOf(';') != -1 || key.indexOf(0) != -1) { Log.e(TAG, "Key \"" + key + "\" contains invalid character (= or ; or \\0)"); return; } if (value.indexOf('=') != -1 || value.indexOf(';') != -1 || value.indexOf(0) != -1) { Log.e(TAG, "Value \"" + value + "\" contains invalid character (= or ; or \\0)"); return; } put(key, value); } /** * Sets an integer parameter. * * @param key the key name for the parameter * @param value the int value of the parameter */ public void set(String key, int value) { put(key, Integer.toString(value)); } private void put(String key, String value) { /* * Remove the key if it already exists. * * This way setting a new value for an already existing key will always move * that key to be ordered the latest in the map. */ mMap.remove(key); mMap.put(key, value); } private void set(String key, List<Area> areas) { if (areas == null) { set(key, "(0,0,0,0,0)"); } else { StringBuilder buffer = new StringBuilder(); for (int i = 0; i < areas.size(); i++) { Area area = areas.get(i); Rect rect = area.rect; buffer.append('('); buffer.append(rect.left); buffer.append(','); buffer.append(rect.top); buffer.append(','); buffer.append(rect.right); buffer.append(','); buffer.append(rect.bottom); buffer.append(','); buffer.append(area.weight); buffer.append(')'); if (i != areas.size() - 1) buffer.append(','); } set(key, buffer.toString()); } } /** * Returns the value of a String parameter. * * @param key the key name for the parameter * @return the String value of the parameter */ public String get(String key) { return mMap.get(key); } /** * Returns the value of an integer parameter. * * @param key the key name for the parameter * @return the int value of the parameter */ public int getInt(String key) { return Integer.parseInt(mMap.get(key)); } // 设置预览画面大小,若预览已经启动,则必须现停止预览,重新设置所需参数, // 设置此值需综合考虑显示旋转角度; public void setPreviewSize(int width, int height); // 获取预览画面大小; public Size getPreviewSize(); // 获取所支持的预览画面大小参数值,返回一个列表; public List<Size> getSupportedPreviewSizes(); // 获取所支持的录像图像大小,返回一个列表 public List<Size> getSupportedVideoSizes(); // 获取被推荐的预览图像大小用于预览和录像 public Size getPreferredPreviewSizeForVideo(); // JPEG thumbnail大小设置 public void setJpegThumbnailSize(int width, int height); // JPEG thumbnail大小获取 public Size getJpegThumbnailSize(); // 获取所支持的拍照Thumbnail大小 public List<Size> getSupportedJpegThumbnailSizes(); // 设置Thumbnail图像质量[0~100], 100为最佳质量 public void setJpegThumbnailQuality(int quality); // 获取当前Thumbnail图像质量 public int getJpegThumbnailQuality(); // 设置拍照图片图像质量 public void setJpegQuality(int quality); // 获取拍照图片图像质量 public int getJpegQuality(); // 设置预览帧率,这只是一个预想值,具体要看驱动是否能达到, 后续被setPreviewFpsRange(int,int)替代 public void setPreviewFrameRate(int fps); // 获取预览帧率,这只是一个预想值,具体要看驱动是否能达到, 后续被getPreviewFpsRange(int[])替代 public int getPreviewFrameRate(); // 获取所支持的预览帧率,返回一个list列表,后续被getSupportedPreviewFpsRange()替代 public List<Integer> getSupportedPreviewFrameRates(); // 设置预览帧率范围,最大值和最小值必须乘以1000,此值用来控制PreviewCallback速率 public void setPreviewFpsRange(int min, int max); // 获取当前预览帧率最大值和最小值, 计算实际帧率必须除以1000,可以通过PREVIEW_FPS_MIN_INDEX // PREVIEW_FPS_MAX_INDEX来确定返回数组中那个是最大值,那个是最小值, public void getPreviewFpsRange(int[] range); // 获取所支持的预览帧率范围,每一个组值分别有最大值和最小值,返回的是一个列表, // 期望的实际帧率在所设置的帧率范围之内, public List<int[]> getSupportedPreviewFpsRange(); // 设置preview时的video数据格式,若没有设置则默认为ImageFormat.NV21,因为在视频录制是所需格式为ImageFormat.NV21; // 可以通过getSupportedPreviewFormats()来获取所支持的video数据格式,返回一个列表; // 强烈建议使用ImageFormat.NV21和ImageFormat.YV12,因为绝大多数Camera都支持这两种数据格式; public void setPreviewFormat(int pixel_format); // 获取preview时的video数据格式; public int getPreviewFormat(); // 获取所支持的video数据格式,返回一个列表; public List<Integer> getSupportedPreviewFormats(); // 设置拍照图片大小 public void setPictureSize(int width, int height); // 获取当前拍照图片大小 public Size getPictureSize(); // 获取所支持的拍照图片大小,返回一个列表 public List<Size> getSupportedPictureSizes(); // 设置拍照图片格式,期望支持的有ImageFormat.NV21, ImageFormat.RGB_565, ImageFormat.JPEG public void setPictureFormat(int pixel_format); // 获取当前拍照图片格式 public int getPictureFormat(); // 获取所支持的拍照图片格式,返回一个列表 public List<Integer> getSupportedPictureFormats(); private String cameraFormatForPixelFormat(int pixel_format) { switch(pixel_format) { case ImageFormat.NV16: return PIXEL_FORMAT_YUV422SP; case ImageFormat.NV21: return PIXEL_FORMAT_YUV420SP; case ImageFormat.YUY2: return PIXEL_FORMAT_YUV422I; case ImageFormat.YV12: return PIXEL_FORMAT_YUV420P; case ImageFormat.RGB_565: return PIXEL_FORMAT_RGB565; case ImageFormat.JPEG: return PIXEL_FORMAT_JPEG; default: return null; } } private int pixelFormatForCameraFormat(String format) { if (format == null) return ImageFormat.UNKNOWN; if (format.equals(PIXEL_FORMAT_YUV422SP)) return ImageFormat.NV16; if (format.equals(PIXEL_FORMAT_YUV420SP)) return ImageFormat.NV21; if (format.equals(PIXEL_FORMAT_YUV422I)) return ImageFormat.YUY2; if (format.equals(PIXEL_FORMAT_YUV420P)) return ImageFormat.YV12; if (format.equals(PIXEL_FORMAT_RGB565)) return ImageFormat.RGB_565; if (format.equals(PIXEL_FORMAT_JPEG)) return ImageFormat.JPEG; return ImageFormat.UNKNOWN; } // 设置图像旋转角度,0,90,180,270. public void setRotation(int rotation); // GPS纬度信息,用于拍照 public void setGpsLatitude(double latitude); // GPS经度信息,用于拍照 public void setGpsLongitude(double longitude); // GPS海拔信息,用于拍照 public void setGpsAltitude(double altitude); // GPS时间信息,用于拍照 public void setGpsTimestamp(long timestamp); // GPS信息处理方式,用于拍照 public void setGpsProcessingMethod(String processing_method); /** * Removes GPS latitude, longitude, altitude, and timestamp from the * parameters. */ public void removeGpsData() { remove(KEY_GPS_LATITUDE); remove(KEY_GPS_LONGITUDE); remove(KEY_GPS_ALTITUDE); remove(KEY_GPS_TIMESTAMP); remove(KEY_GPS_PROCESSING_METHOD); } // 获取当前WB模式 public String getWhiteBalance(); // 设置WB模式 public void setWhiteBalance(String value); // 获取所支持的WB模式,模式有:AUTO,INCANDESCENT,FLUORESCENT,WARM_FLUORESCENT,DAYLIGHT,CLOUDY_DAYLIGHT,TWILIGHT,SHADE public List<String> getSupportedWhiteBalance(); // 获取色彩效果 public String getColorEffect(); // 设置色彩效果 public void setColorEffect(String value); // 获取camera设备所支持的色彩效果 // 色彩效果有NONE,MONO,NEGATIVE,SOLARIZE,SEPIA,POSTERIZE,WHITEBOARD,BLACKBOARD,AQUA public List<String> getSupportedColorEffects(); // 获取当前Antibinding模式 public String getAntibanding(); // 设置Antibinding模式 public void setAntibanding(String antibanding); // 获取设备所支持的Antibinding模式 public List<String> getSupportedAntibanding(); // 获取当前的场景模式,场景模式有:AUTO,ACTION,PORTRAIT,LANDSCAPE,NIGHT, // NIGHT_PORTRAIT,THEATRE,BEACH, SNOW, SUNSET,STEADYPHOTO,FIREWORKS,SPORTS,PARTY,CANDLELIGHT, BARCODE public String getSceneMode(); // 设置场景模式 public void setSceneMode(String value); // 获取所支持的场景模式 public List<String> getSupportedSceneModes(); // 获取当前闪光灯模式 // 闪光灯模式有: OFF,AUTO,ON,RED_EYE,TORCH public String getFlashMode() { return get(KEY_FLASH_MODE); } // 设置闪光灯模式 public void setFlashMode(String value); // 设置系统设备所支持的闪光灯模式 public List<String> getSupportedFlashModes(); // 获取当前设备对应的对焦模式 // 对焦模式有: AUTO,INFINITY,MACRO,FIXED,EDOF,CONTINUOUS_VIDEO public String getFocusMode(); // 设置对焦模式 public void setFocusMode(String value); // 获取系统所支持的对焦模式 public List<String> getSupportedFocusModes(); // 获取焦距 public float getFocalLength(); // 水平视角 public float getHorizontalViewAngle(); // 垂直视角 public float getVerticalViewAngle(); // 获取当前曝光补偿序号 public int getExposureCompensation(); // 设置曝光补偿序号 public void setExposureCompensation(int value); // 获取支持的最大曝光补偿序号 public int getMaxExposureCompensation(); // 获取支持的最小曝光补偿序号 public int getMinExposureCompensation(); // 获取曝光补偿步长 public float getExposureCompensationStep(); // 自动曝光锁定,使用者调用前必须通过isAutoExposureLockSupported()判定是否支持该操作, // 若设置为true,自动曝光程序将立即暂停直到调用此接口设置为false,在自动曝光锁定时,曝光补偿设置仍然是有效的, // 重复设置自动曝光锁定不影响之前的设定,调用stopPreview()和takePicture()将不会改变锁定状态。 public void setAutoExposureLock(boolean toggle); // 获取自动曝光锁定状态 public boolean getAutoExposureLock(); // 判定自动曝光锁定是否支持 public boolean isAutoExposureLockSupported(); // 自动白平衡锁定设置,使用者必须通过isAutoWhiteBalanceLockSupported()判定自动白平衡锁定设置是否支持, // 若设置为true,自动白平衡程序将立即暂停直到调用此接口设置为false, // 重复设置自动曝光锁定不影响之前的设定,调用stopPreview()和takePicture()将不会改变锁定状态。 public void setAutoWhiteBalanceLock(boolean toggle); // 获取自动白平衡锁定状态 public boolean getAutoWhiteBalanceLock(); // 判定自动白平衡锁定是否支持 public boolean isAutoWhiteBalanceLockSupported(); // 获取当前的缩放值,范围[0~getMaxZoom()]. 0代表没有缩放, // 使用之前通过isZoomSupported()判定是否支持缩放 public int getZoom(); // 设置缩放值 public void setZoom(int value); // 判定缩放是否支持 public boolean isZoomSupported(); // 获取最大缩放值 public int getMaxZoom(); // 缩放比,需要除以100,来表示,3.2x--->320, 第一个值为100, 最后一个为最大缩放比 public List<Integer> getZoomRatios(); // 判定是否支持平滑缩放 public boolean isSmoothZoomSupported(); // 对焦过程中 物体到焦点的距离,会时时变化 public void getFocusDistances(float[] output); // 对焦区域的最大个数 public int getMaxNumFocusAreas(); // 获取camera的对焦区域 public List<Area> getFocusAreas(); // 设置对焦区域, camera驱动将会使用此区域来进行对焦 public void setFocusAreas(List<Area> focusAreas); // 获取所支持曝光区域最大个数 public int getMaxNumMeteringAreas(); // 获取当前曝光区域设定 public List<Area> getMeteringAreas(); // 设置曝光区域 public void setMeteringAreas(List<Area> meteringAreas); // 硬件加速人脸识别的支持的最大个数 public int getMaxNumDetectedFaces(); // 示将会开启视频录制,而不是照相 public void setRecordingHint(boolean hint); // 视频录制时是否支持快照 public boolean isVideoSnapshotSupported(); // 在相机预览或视频录制时开启或关闭抖动抑制,不能在拍照时抑制运动模糊 public void setVideoStabilization(boolean toggle); // 获取抖动抑制(视频稳定)状态 public boolean getVideoStabilization(); // 是否支持视频稳定设置 public boolean isVideoStabilizationSupported(); // Splits a comma delimited string to an ArrayList of String. // Return null if the passing string is null or the size is 0. private ArrayList<String> split(String str) { if (str == null) return null; TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); splitter.setString(str); ArrayList<String> substrings = new ArrayList<String>(); for (String s : splitter) { substrings.add(s); } return substrings; } // Splits a comma delimited string to an ArrayList of Integer. // Return null if the passing string is null or the size is 0. private ArrayList<Integer> splitInt(String str) { if (str == null) return null; TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); splitter.setString(str); ArrayList<Integer> substrings = new ArrayList<Integer>(); for (String s : splitter) { substrings.add(Integer.parseInt(s)); } if (substrings.size() == 0) return null; return substrings; } private void splitInt(String str, int[] output) { if (str == null) return; TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); splitter.setString(str); int index = 0; for (String s : splitter) { output[index++] = Integer.parseInt(s); } } // Splits a comma delimited string to an ArrayList of Float. private void splitFloat(String str, float[] output) { if (str == null) return; TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); splitter.setString(str); int index = 0; for (String s : splitter) { output[index++] = Float.parseFloat(s); } } // Returns the value of a float parameter. private float getFloat(String key, float defaultValue) { try { return Float.parseFloat(mMap.get(key)); } catch (NumberFormatException ex) { return defaultValue; } } // Returns the value of a integer parameter. private int getInt(String key, int defaultValue) { try { return Integer.parseInt(mMap.get(key)); } catch (NumberFormatException ex) { return defaultValue; } } // Splits a comma delimited string to an ArrayList of Size. // Return null if the passing string is null or the size is 0. private ArrayList<Size> splitSize(String str) { if (str == null) return null; TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); splitter.setString(str); ArrayList<Size> sizeList = new ArrayList<Size>(); for (String s : splitter) { Size size = strToSize(s); if (size != null) sizeList.add(size); } if (sizeList.size() == 0) return null; return sizeList; } // Parses a string (ex: "480x320") to Size object. // Return null if the passing string is null. private Size strToSize(String str) { if (str == null) return null; int pos = str.indexOf('x'); if (pos != -1) { String width = str.substring(0, pos); String height = str.substring(pos + 1); return new Size(Integer.parseInt(width), Integer.parseInt(height)); } Log.e(TAG, "Invalid size parameter string=" + str); return null; } // Splits a comma delimited string to an ArrayList of int array. // Example string: "(10000,26623),(10000,30000)". Return null if the // passing string is null or the size is 0. private ArrayList<int[]> splitRange(String str) { if (str == null || str.charAt(0) != '(' || str.charAt(str.length() - 1) != ')') { Log.e(TAG, "Invalid range list string=" + str); return null; } ArrayList<int[]> rangeList = new ArrayList<int[]>(); int endIndex, fromIndex = 1; do { int[] range = new int[2]; endIndex = str.indexOf("),(", fromIndex); if (endIndex == -1) endIndex = str.length() - 1; splitInt(str.substring(fromIndex, endIndex), range); rangeList.add(range); fromIndex = endIndex + 3; } while (endIndex != str.length() - 1); if (rangeList.size() == 0) return null; return rangeList; } // Splits a comma delimited string to an ArrayList of Area objects. // Example string: "(-10,-10,0,0,300),(0,0,10,10,700)". Return null if // the passing string is null or the size is 0 or (0,0,0,0,0). private ArrayList<Area> splitArea(String str) { if (str == null || str.charAt(0) != '(' || str.charAt(str.length() - 1) != ')') { Log.e(TAG, "Invalid area string=" + str); return null; } ArrayList<Area> result = new ArrayList<Area>(); int endIndex, fromIndex = 1; int[] array = new int[5]; do { endIndex = str.indexOf("),(", fromIndex); if (endIndex == -1) endIndex = str.length() - 1; splitInt(str.substring(fromIndex, endIndex), array); Rect rect = new Rect(array[0], array[1], array[2], array[3]); result.add(new Area(rect, array[4])); fromIndex = endIndex + 3; } while (endIndex != str.length() - 1); if (result.size() == 0) return null; if (result.size() == 1) { Area area = result.get(0); Rect rect = area.rect; if (rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0 && area.weight == 0) { return null; } } return result; } private boolean same(String s1, String s2) { if (s1 == null && s2 == null) return true; if (s1 != null && s1.equals(s2)) return true; return false; } };