android usb cameraCamera设置参数failed,该如何解决怎么解决

Android系统如何使用Camera拍照 参数设置
  shutter:在按下快门的时候回调,这里可以播放一段声音。
  raw:从Camera获取到未经处理的图像。
  postview:从Camera获取一个快速预览的图片,不是所有设备都支持。
  jpeg:从Camera获取到一个经过压缩的jpeg图片。
  Camera的参数设置
  它将以异步的方式从Camera中获取图像,具有多个回调类作为参数,并且都可以为null,下面分别介绍这些参数的意义:
  在开发Android应用的时候,如果需要调用摄像头获取拍摄的照片,除了通过Intent调用系统现有相机应用拍摄照片之外,还可以通过直接调用Camera硬件去去获取摄像头拍摄的照片。本篇博客将讲解如何在Android应用中通过Camera拍摄照片,这个对开发相机类应用尤为重要,同样最后也将以一个简单的Demo演示。
  final void setErrorCallback(Camera.ErrorCallback cb):Camera发送错误的时候回调,可以在其中进行错误的后续处理。
  final void setPreviedCallback(Camera.PreviewCallback cb):Camera预览界面发生变化的时候回调,可以在其中获取到Camera捕获到的帧图像。
  FEATURE_CAMERA:设备是否有摄像头。
  FEATURE_CAMERA_ANY:设备至少有一个摄像头。
  FEATURE_CAMERA_AUTOFOCUS:设备支持的摄像头是否支持自动对焦
  FEATURE_CAMERA_FLASH:设备是否配备闪光灯。
  FEATURE_CAMERA_FRONT:设备是否有一个前置摄像头。
  Camera
  Camera捕获画面的预览
  Camera的预览,需要放到一个SurfaceView中,出于安全的考虑,在设计Android的时候就规定,如果需要调用Camera,必须为其制定显示在屏幕上的SurfaceView预览,否则将无法使用Camera。关于SurfaceView和SurfaceHolder的内容,在之前的博客中已经详细讲解,这里不再累述,不清楚的朋友可以看看之前的博客:Android--SurfaceView。
  public final void taskPicture(Camera.ShuffterCallback shutter,Camera.PictureCallback raw,Camera.PictureCallback postview,Camera.PictureCallback jpeg)
  使用open()方法获取一个Camera对象,鉴于Android设备可能配置了多个摄像头,open()方法可以通过摄像头Id开启指定的摄像头。
  为Camera对象设置预览类,它是一个SurfaceHolder对象,通过setPreviewDisplay(SurfaceHolder)方法设置。
  调用startPreview()方法开始Camera对象的预览。
  调用takePicture()方法进行拍照,其中可以通过Camera.PictureCallback()回调获得拍摄的Image数据。
  当拍摄完成后,需要调用stopPreview()方法停止预览,并使用release()释放Camera占用的资源。
  如果直接使用taskPicture()进行拍照的话,Camera是不会进行自动对焦的,这里需要使用Camera.autoFocus()方法进行对焦,它传递一个Camera.AutoFocusCallback参数,用于自动对焦完成后回调,一般会在它对焦完成在进行taskPicture()拍照。
  实现代码:MainActivity.java
  Camera是Android摄像头硬件的相机类,位于硬件包&android.hardware.Camera&下。它主要用于摄像头捕获图片、启动/停止预览图片、拍照、获取视频帧等,它是设备本地的服务,负责管理设备上的摄像头硬件。
  使用Camera拍照的Demo
  3 android:orientation=&horizontal&
  4 android:layout_width=&fill_parent&
  5 android:layout_height=&fill_parent&
  8 android:id=&@+id/camera_preview&
  9 android:layout_width=&fill_parent&
  10 android:layout_height=&fill_parent&
  11 android:layout_weight=&1&
  15 android:id=&@+id/button_capture&
  16 android:text=&拍照&
  17 android:layout_width=&wrap_content&
  18 android:layout_height=&wrap_content&
  19 android:layout_gravity=&center&
  2 private boolean checkCameraHardware(Context context) {
  3 if (context.getPackageManager().hasSystemFeature(
  4 PackageManager.FEATURE_CAMERA)) {
  5 // 存在
  7 } else {
  8 // 不存在
  1 package cn.bgxt.
  3 import java.io.IOE
  4 import android.content.C
  5 import android.hardware.C
  6 import android.util.L
  7 import android.view.SurfaceH
  8 import android.view.SurfaceV
  13 public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
  14 private static final String TAG = &main&;
  15 private SurfaceHolder mH
  16 private Camera mC
  18 public CameraPreview(Context context, Camera camera) {
  19 super(context);
  20 mCamera =
  22 // 通过SurfaceView获得SurfaceHolder
  23 mHolder = getHolder();
  24 // 为SurfaceHolder指定回调
  25 mHolder.addCallback(this);
  26 // 设置Surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到界面在Android3.0之后弃用
  27 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  30 public void surfaceCreated(SurfaceHolder holder) {
  31 // 当Surface被创建之后,开始Camera的预览
  32 try {
  33 mCamera.setPreviewDisplay(holder);
  34 mCamera.startPreview();
  35 } catch (IOException e) {
  36 Log.d(TAG, &预览失败&);
  40 public void surfaceDestroyed(SurfaceHolder holder) {
  44 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
  45 // Surface发生改变的时候将被调用,第一次显示到界面的时候也会被调用
  46 if (mHolder.getSurface() == null){
  47 // 如果Surface为空,不继续操作
  51 // 停止Camera的预览
  52 try {
  53 mCamera.stopPreview();
  54 } catch (Exception e){
  55 Log.d(TAG, &当Surface改变后,停止预览出错&);
  58 // 在预览前可以指定Camera的各项参数
  60 // 重新开始预览
  61 try {
  62 mCamera.setPreviewDisplay(mHolder);
  63 mCamera.startPreview();
  65 } catch (Exception e){
  66 Log.d(TAG, &预览Camera出错&);
  1 package cn.bgxt.
  3 import java.io.F
  4 import java.io.FileOutputS
  6 import android.os.B
  7 import android.util.L
  8 import android.view.V
  9 import android.widget.B
  10 import android.widget.FrameL
  11 import android.app.A
  12 import android.content.C
  13 import android.content.pm.PackageM
  14 import android.hardware.C
  15 import android.hardware.Camera.AutoFocusC
  16 import android.hardware.Camera.PictureC
  18 public class MainActivity extends Activity {
  19 protected static final String TAG = &main&;
  20 private Camera mC
  21 private CameraPreview mP
  23 @Override
  24 protected void onCreate(Bundle savedInstanceState) {
  25 super.onCreate(savedInstanceState);
  26 setContentView(R.layout.activity_main);
  28 mCamera = getCameraInstance();
  30 // 创建预览类,并与Camera关联,最后添加到界面布局中
  31 mPreview = new CameraPreview(this, mCamera);
  32 FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
  33 preview.addView(mPreview);
  36 Button captureButton = (Button) findViewById(R.id.button_capture);
  37 captureButton.setOnClickListener(new View.OnClickListener() {
  38 @Override
  39 public void onClick(View v) {
  40 // 在捕获图片前进行自动对焦
  41 mCamera.autoFocus(new AutoFocusCallback() {
  43 @Override
  44 public void onAutoFocus(boolean success, Camera camera) {
  45 // 从Camera捕获图片
  46 mCamera.takePicture(null, null, mPicture);
  48 });
  50 });
  54 private boolean checkCameraHardware(Context context) {
  55 if (context.getPackageManager().hasSystemFeature(
  56 PackageManager.FEATURE_CAMERA)) {
  57 // 存在
  59 } else {
  60 // 不存在
  66 public static Camera getCameraInstance() {
  67 Camera c =
  68 try {
  69 c = Camera.open();
  70 } catch (Exception e) {
  71 Log.d(TAG, &打开Camera失败失败&);
  76 private PictureCallback mPicture = new PictureCallback() {
  78 @Override
  79 public void onPictureTaken(byte[] data, Camera camera) {
  80 // 获取Jpeg图片,并保存在sd卡上
  81 File pictureFile = new File(&/sdcard/& + System.currentTimeMillis()
  82 + &.jpg&);
  83 try {
  84 FileOutputStream fos = new FileOutputStream(pictureFile);
  85 fos.write(data);
  86 fos.close();
  87 } catch (Exception e) {
  88 Log.d(TAG, &保存图片失败&);
  93 @Override
  94 protected void onDestroy() {
  95 // 回收Camera资源
  96 if(mCamera!=null){
  97 mCamera.stopPreview();
  98 mCamera.release();
  99 mCamera=
  101 super.onDestroy();
  验证设备是否配备摄像头硬件
  虽然raw、postview、jpeg都是Camera.PictureCallback回调,但是一般我们只需要获取jpeg,其他传null即可,Camera.PictureCallback里需要实现一个方法onPictureTaken(byte[] data,Camera camera),data及为图像数据。值得注意的是,一般taskPicture()方法拍照完成之后,SurfaceView都会停留在拍照的瞬间,需要重新调用startPreview()才会继续预览。
  上面已经介绍了Camera的常用方法,下面根据这些方法详细讲解Android下使用Camera开发拍照应用最基本的过程:
  Camera既然用于管理设备上的摄像头硬件,那么它也为开发人员提供了相应的方法,并且这些方法大部分都是native的,用C++在底层实现,下面简单介绍一下Camera的一些方法:
  Camera的回调监听
  下面我们直接使用一个类去继承SurfaceView当做Camera的预览类:
  使用Camera拍照
  一般而言,检测FEATURE_CAMERA即可:  
  Camera作为一个摄像头硬件的调用类,还为我们提供了详细的设置摄像头各项参数的方法,比如闪光灯的模式、自动对焦的模式等。步骤是使用Camera.getParameters()方法获取到Camera.Parameters对象,在其中设置好摄像头的各项参数后,再通过Camera.setParameters()方法写入到Camera对象中即可。这个设置必须在使用startPreview()之前完成。关于Camera参数的设置,比较细致,不在本篇博客的内容之中,以后有机会再详细介绍。
  效果展示
  因为Android的开源,所以其支持的设备多而杂,在使用Camera的时候,最好验证一下当前运行的设备上是否配备了摄像头硬件。这里需要用到一个PackageManager,它用于检测应用安装设备的各种信息,可以通过Context.getPackageManager()方法获取。可以通过PackageManager.hasSystemFeature(String name)方法检测设备是否支持摄像头操作,它传递的是一个String类型的参数,被PackageManager定义为了常量,返回一个Boolean数据,验证是否检测通过,对于Camera而言,可以检测如下信息:
  当指定了Camera的预览类,并开始预览之后,就可以通过takePicture()方法进行拍照了,下面是它的完整签名:
  上面介绍Camera拍照的时候介绍了两个回调,Camera还提供了一些其他的回调的事件监听方法,这里简单介绍几个常用的:
  本篇博客的主要内容:
  static Camera open():打开Camera,返回一个Camera实例。
  static Camera open(int cameraId):根据cameraId打开一个Camera,返回一个Camera实例。
  final void release():释放掉Camera的资源。
  static int getNumberOfCameras():获取当前设备支持的Camera硬件个数。
  Camera.Parameters getParameters():获取Camera的各项参数设置类。
  void setParameters(Camera.Parameters params):通过params把Camera的各项参数写入到Camera中。
  final void setDisplayOrientation(int degrees):摄像预览的旋转度。
  final void setPreviewDisplay(SurfaceHolder holder):设置Camera预览的SurfaceHolder。
  final void starPreview():开始Camera的预览。
  final void stopPreview():停止Camera的预览
  final void autoFocus(Camera.AutoFocusCallback cb):自动对焦。
  final takePicture(Camera.ShutterCallback shutter,Camera.PictureCallback raw,Camera.PictureCallback jpeg):拍照。
  final void lock():锁定Camera硬件,使其他应用无法访问。
  final void unlock():解锁Camera硬件,使其他应用可以访问。
  上面已经定义好了SurfaceView,它是一个Camera的预览类,下面直接通过一个示例演示Camera是如何进行拍照的,备注都比较详细,这里不再累述了。
  源码下载
  布局代码:activity_main.xml
  Camera
  验证设备是否配备摄像头硬件
  Camera捕获画面的预览
  使用Camera拍照
  使用Camera拍照的Demo
  Camera的回调监听
  Camera的参数设置
  上面已经介绍了使用Camera的基本步骤以及涉及的内容,这里通过一个简单的Demo演示一下,使用上面附上代码的预览类进行Camera预览。代码中注释比较完整,这里不再累述。
  以上介绍的步骤都是最基本的过程,是必不可少的。Camera没有提供公开的构造函数,只能通过open()方法获取,并且必须设置一个预览类SurfaceHolder,如果不设置的话,将无法使用Camera。在使用完成Camera之后,必须使用release()释放Camera资源。 本文网址 //21209.html
更多相关资讯
推荐 精华文章
声明:本站所有文章内容均由网友提供或转载于互联网,版权归为作者所有
若有文章侵犯了您的权益,请马上联系删除。
苏ICP备号-4Android Camera(二) Camera程序编写 - 圣骑士wind - 博客园
随笔 - 367, 文章 - 8, 评论 - 353, 引用 - 0
Android Camera 相机程序编写
  要自己写一个相机应用直接使用相机硬件,首先应用需要一个权限设置,在AndroidManifest.xml中加上使用设备相机的权限:
&uses-permission android:name="android.permission.CAMERA" /&
  为你的应用创建自定义的相机,一般步骤如下:
  1.检测相机硬件并获取访问
  2.建立一个Preview类:需要一个相机预览的类,继承&&类,并实现接口。
  3.建立预览的布局。
  4.为拍照建立监听。
  5.拍照并且存储文件。
  6.释放相机。
  因为相机是一个共享资源,所以应该被谨慎管理,这样应用之间才不会发生冲突。
  所以使用完相机之后应该调用&来释放相机对象。
  如果不释放,后续的使用相机请求(其他应用或本应用)都会失败。
检测相机硬件
  如果你的程序没有在manifest的声明中要求有相机,那么你应该在运行时检查相机的存在与否,主要用了&&方法。比如:
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context)
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA))
// this device has a camera
return true;
// no camera on this device
return false;
  设备上可能有多个相机,Android 2.3以后可以使用&来查看相机的数目。
  如下面这段程序用于检测设备中的相机,并得到默认相机的索引号:
private int getDefaultCameraId()
int defaultId = -1;
// Find the total number of cameras available
mNumberOfCameras = Camera.getNumberOfCameras();
// Find the ID of the default camera
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i & mNumberOfC i++)
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK)
defaultId =
if (-1 == defaultId)
if (mNumberOfCameras & 0)
// 如果没有后向摄像头
defaultId = 0;
// 没有摄像头
Toast.makeText(getApplicationContext(), R.string.no_camera,
Toast.LENGTH_LONG).show();
return defaultId;
  看了Camera类的代码实现后,其中不带参数的open()方法:
public static Camera open()
int numberOfCameras = getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i & numberOfC i++)
getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK)
return new Camera(i);
return null;
  说明open方法默认是打开第一个后向摄像头的。
  当检测到设备上有相机之后,必须获取其访问权,获取一个&&类的对象。
  要获取主要的相机,可以使用&&方法,注意异常处理。
  在使用这个方法的时候一定要检查异常,如果相机正在被使用或者不存在,没有处理异常,将会使得应用被系统关闭。
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance()
Camera c = null;
c = Camera.open(); // attempt to get a Camera instance
catch (Exception e)
// Camera is not available (in use or does not exist)
return // returns null if camera is unavailable
  Android 2.3之后,可以使用来获取特定的相机。
检查相机特性
  可以使用方法来检查相机的特性。
  API Level 9之后,可以使用&来查看相机是在设备前面还是后面,还可以得到图像的方向。
建立Preview类
  为了有效地拍照或录像,用户必须要看到相机能看到的图像。
  相机的preview类是一个&&,展示了相机正在捕捉的图像。
  下面是一个预览类的例子(来自官网):
A basic preview class
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mH
private Camera mC
public CameraPreview(Context context, Camera camera) {
super(context);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
// stop preview before making changes
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
  注意要设置尺寸的话需要放在surfaceChanged()方法里,调用&方法,并且应该使用&返回的值,而不要使用任意的尺寸。
把Preview放在布局里面
  布局时可以使用FrameLayout,这样其他的按钮或者元素可以叠加在预览图像上。
  对于大多数设备来说,相机预览的默认方向是横放的(landscape)。
  从Android 2.2 (API Level 8)开始,可以使用&来设置预览图像的方向。
  如果需要在用户改变设备方向的时候改变预览图像的方向,可以在&方法中,首先用&&停止预览,改变方向,然后用开启新的预览。
  当然你也可以直接在manifest中设置好方向,如下:
&activity android:name=".CameraActivity"
android:label="@string/app_name"
android:screenOrientation="landscape"&
&!-- configure this activity to use landscape orientation --&
&intent-filter&
&action android:name="android.intent.action.MAIN" /&
&category android:name="android.intent.category.LAUNCHER" /&
&/intent-filter&
&/activity&
  在应用里面,必须为用户控制加上监听,来响应用户拍照的动作。
  为了得到图像,要使用&方法。
  这个方法接收三个参数,用于从相机获取图像。
  为了接收到JPEG格式的数据,需要实现接口用来接收图像数据并且写入文件。
  下面的代码展示了一个最基本的实现:
private PictureCallback mPicture = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: " +
e.getMessage());
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
  照相动作可以用按钮控制,如下:
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
  相机是设备资源,被所有应用共享,当应用不使用相机时应当及时释放,应当在中释放。
  如果不及时释放,后续的相机请求(包括你自己的应用和其他的应用发出的)都将失败并且导致应用退出。
  完整的照相程序需要考虑相机切换、预览图像的尺寸设置、焦距变换、缩放、白平衡的相机参数设置。
  请查阅文后的参考资料进行进一步学习。
  附上一个粗糙待完善的自定义相机程序()
  预览图像类: 
CameraPreview
package com.example.
import java.io.IOE
import java.util.L
import android.R.
import android.content.C
import android.graphics.ImageF
import android.graphics.PixelF
import android.hardware.C
import android.hardware.Camera.CameraI
import android.hardware.Camera.S
import android.util.AttributeS
import android.util.L
import android.view.SurfaceH
import android.view.SurfaceV
* 相机图片预览类
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback
private SurfaceHolder mH
private Camera mC
Size mPreviewS
List&Size& mSupportedPreviewS
public CameraPreview(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
public CameraPreview(Context context, AttributeSet attrs)
super(context, attrs);
public CameraPreview(Context context)
super(context);
* 初始化工作
private void init()
Log.d(AppConstants.LOG_TAG, "CameraPreview initialize");
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
public void setCamera(Camera camera)
if (mCamera != null)
mSupportedPreviewSizes = mCamera.getParameters()
.getSupportedPreviewSizes();
requestLayout();
public void surfaceCreated(SurfaceHolder holder)
Log.d(AppConstants.LOG_TAG, "surfaceCreated");
// The Surface has been created, now tell the camera where to draw the
// preview.
if (null != mCamera)
mCamera.setPreviewDisplay(holder);
catch (IOException e1)
e1.printStackTrace();
Log.d(AppConstants.LOG_TAG,
"Error setting camera preview display: " + e1.getMessage());
if (null != mCamera)
mCamera.startPreview();
Log.d(AppConstants.LOG_TAG, "surfaceCreated successfully! ");
catch (Exception e)
Log.d(AppConstants.LOG_TAG,
"Error setting camera preview: " + e.getMessage());
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
Log.d(AppConstants.LOG_TAG, "surface changed");
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (null == mHolder.getSurface())
// preview surface does not exist
// stop preview before making changes
if (null != mCamera)
mCamera.stopPreview();
catch (Exception e)
// ignore: tried to stop a non-existent preview
// set preview size and make any resize, rotate or
// reformatting changes here
if (null != mCamera)
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
Log.d(AppConstants.LOG_TAG, "camera set parameters successfully!: "
+ parameters);
// 这里可以用来设置尺寸
// start preview with new settings
if (null != mCamera)
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
catch (Exception e)
Log.d(AppConstants.LOG_TAG,
"Error starting camera preview: " + e.getMessage());
public void surfaceDestroyed(SurfaceHolder holder)
Log.d(AppConstants.LOG_TAG, "surfaceDestroyed");
if (null != mCamera)
mCamera.stopPreview();
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// We purposely disregard child measurements because act as a
// wrapper to a SurfaceView that centers the camera preview instead
// of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(),
widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(),
heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null)
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width,
private Size getOptimalPreviewSize(List&Size& sizes, int w, int h)
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w /
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight =
// Try to find an size match aspect ratio and size
for (Size size : sizes)
double ratio = (double) size.width / size.
if (Math.abs(ratio - targetRatio) & ASPECT_TOLERANCE)
if (Math.abs(size.height - targetHeight) & minDiff)
optimalSize =
minDiff = Math.abs(size.height - targetHeight);
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null)
minDiff = Double.MAX_VALUE;
for (Size size : sizes)
if (Math.abs(size.height - targetHeight) & minDiff)
optimalSize =
minDiff = Math.abs(size.height - targetHeight);
return optimalS
  主要的Activity类:
HelloCustomCameraActivity
package com.example.
import java.io.F
import java.io.FileNotFoundE
import java.io.FileOutputS
import java.io.IOE
import java.text.SimpleDateF
import java.util.D
import android.app.A
import android.content.C
import android.content.pm.PackageM
import android.hardware.C
import android.hardware.Camera.CameraI
import android.hardware.Camera.PictureC
import android.os.B
import android.os.E
import android.util.L
import android.view.D
import android.view.V
import android.view.W
import android.view.WindowM
import android.widget.B
import android.widget.FrameL
import android.widget.T
public class HelloCustomCameraActivity extends Activity
private Camera mC
private CameraPreview mP
int mNumberOfC
int mCameraCurrentlyL
// The first rear facing camera
int mDefaultCameraId;
int mScreenWidth, mScreenH
public void onCreate(Bundle savedInstanceState)
Log.d(AppConstants.LOG_TAG, "onCreate");
super.onCreate(savedInstanceState);
// 无标题栏的窗口
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 设置布局
setContentView(R.layout.activity_hello_custom_camera);
// 得到屏幕的大小
WindowManager wManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = wManager.getDefaultDisplay();
mScreenHeight = display.getHeight();
mScreenWidth = display.getWidth();
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
// 将相机预览图加入帧布局里面
preview.addView(mPreview, 0);
// 使用按钮进行拍摄动作监听
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(new View.OnClickListener()
public void onClick(View v)
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
// 得到默认的相机ID
mDefaultCameraId = getDefaultCameraId();
mCameraCurrentlyLocked = mDefaultCameraId;
protected void onResume()
Log.d(AppConstants.LOG_TAG, "onResume");
super.onResume();
// Open the default i.e. the first rear facing camera.
mCamera = getCameraInstance(mCameraCurrentlyLocked);
mPreview.setCamera(mCamera);
protected void onPause()
Log.d(AppConstants.LOG_TAG, "onPause");
super.onPause();
// Because the Camera object is a shared resource, it's very
// important to release it when the activity is paused.
if (mCamera != null)
mPreview.setCamera(null);
Log.d(AppConstants.LOG_TAG, "onPause --& Realease camera");
mCamera.release();
mCamera = null;
protected void onDestroy()
Log.d(AppConstants.LOG_TAG, "onDestroy");
super.onDestroy();
* 得到默认相机的ID
private int getDefaultCameraId()
Log.d(AppConstants.LOG_TAG, "getDefaultCameraId");
int defaultId = -1;
// Find the total number of cameras available
mNumberOfCameras = Camera.getNumberOfCameras();
// Find the ID of the default camera
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i & mNumberOfC i++)
Camera.getCameraInfo(i, cameraInfo);
Log.d(AppConstants.LOG_TAG, "camera info: " + cameraInfo.orientation);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK)
defaultId =
if (-1 == defaultId)
if (mNumberOfCameras & 0)
// 如果没有后向摄像头
defaultId = 0;
// 没有摄像头
Toast.makeText(getApplicationContext(), R.string.no_camera,
Toast.LENGTH_LONG).show();
return defaultId;
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(int cameraId)
Log.d(AppConstants.LOG_TAG, "getCameraInstance");
Camera c = null;
c = Camera.open(cameraId); // attempt to get a Camera instance
catch (Exception e)
// Camera is not available (in use or does not exist)
e.printStackTrace();
Log.e(AppConstants.LOG_TAG, "Camera is not available");
return // returns null if camera is unavailable
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type)
Log.d(AppConstants.LOG_TAG, "getOutputMediaFile");
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = null;
// This location works best if you want the created images to be
// between applications and persist after your app has been
// uninstalled.
mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"MyCameraApp");
Log.d(AppConstants.LOG_TAG,
"Successfully created mediaStorageDir: " + mediaStorageDir);
catch (Exception e)
e.printStackTrace();
Log.d(AppConstants.LOG_TAG, "Error in Creating mediaStorageDir: "
+ mediaStorageDir);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists())
if (!mediaStorageDir.mkdirs())
// 在SD卡上创建文件夹需要权限:
// &uses-permission
// android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&
Log.d(AppConstants.LOG_TAG,
"failed to create directory, check if you have the WRITE_EXTERNAL_STORAGE permission");
return null;
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
File mediaF
if (type == MEDIA_TYPE_IMAGE)
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
else if (type == MEDIA_TYPE_VIDEO)
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "VID_" + timeStamp + ".mp4");
return null;
return mediaF
private PictureCallback mPicture = new PictureCallback()
public void onPictureTaken(byte[] data, Camera camera)
Log.d(AppConstants.LOG_TAG, "onPictureTaken");
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null)
Log.d(AppConstants.LOG_TAG,
"Error creating media file, check storage permissions: ");
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
catch (FileNotFoundException e)
Log.d(AppConstants.LOG_TAG, "File not found: " + e.getMessage());
catch (IOException e)
Log.d(AppConstants.LOG_TAG,
"Error accessing file: " + e.getMessage());
// 拍照后重新开始预览
mCamera.stopPreview();
mCamera.startPreview();
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context)
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA))
// this device has a camera
return true;
// no camera on this device
return false;
  布局文件:
activity_hello_custom_camera.xml
&?xml version="1.0" encoding="utf-8"?&
&LinearLayout xmlns:android="/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" &
&FrameLayout
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" &
android:id="@+id/button_capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:text="Capture" /&
&/FrameLayout&
&/LinearLayout&
  Manifest文件:
AndroidManifest.xml
&manifest xmlns:android="/apk/res/android"
package="com.example.hellocustomcamera"
android:versionCode="1"
android:versionName="1.0" &
android:minSdkVersion="9"
android:targetSdkVersion="15" /&
&uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&
&uses-permission android:name="android.permission.CAMERA" /&
&uses-feature android:name="android.hardware.camera" /&
&application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" &
android:name=".HelloCustomCameraActivity"
android:label="@string/title_activity_hello_custom_camera" &
&!-- android:screenOrientation="landscape" --&
&!-- configure this activity to use landscape orientation --&
&intent-filter&
&action android:name="android.intent.action.MAIN" /&
&category android:name="android.intent.category.LAUNCHER" /&
&/intent-filter&
&/activity&
&/application&
&/manifest&
  三星S5660上测试可以拍照用,其他手机未知。
  Reference: Camera
  相机参数:
  API Guides: Camera
  API Demos:
  com.example.android.apis.graphics包下的CameraPreview
  实例教程:Android设备功能之Camera教程篇:}

我要回帖

更多关于 android camera2 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信