Android Camera 使用小结

来源:互联网 发布:excel数据重复公式 编辑:程序博客网 时间:2024/04/30 19:12

Android Camera 使用小结

Android手机关于Camera的使用,一是拍照,二是摄像,由于Android提供了强大的组件功能,为此对于在Android手机系统上进行Camera的开发,我们可以使用两类方法:一是借助Intent和MediaStroe调用系统Camera App程序来实现拍照和摄像功能,二是根据Camera API自写Camera程序。由于自写Camera需要对Camera API了解很充分,而且对于通用的拍照和摄像应用只需要借助系统Camera App程序就能满足要求了,为此先从调用系统Camera App应用开始来对Android Camera做个简单的使用小结。

调用系统Camera App实现拍照和摄像功能

不是专门的Camera应用,一般用到Camera的需求就是获取照片或者视频,比如微博分享、随手记等,对于在Symbian系统上通过简单地调用系统自带的Camera APP来实现该功能是做不到的,但是Android系统强大的组件特性,使得应用开发者只需通过Intent就可以方便的打开系统自带的Camera APP,并通过MediaStroe方便地获取照片和视频的文件路径。具体我们还是用代码来说话吧:

例1、 实现拍照

在菜单或按钮的选择操作中调用如下代码,开启系统自带Camera APP,并传递一个拍照存储的路径给系统应用程序,具体如下:

imgPath = "/sdcard/test/img.jpg";

//必须确保文件夹路径存在,否则拍照后无法完成回调

File vFile = new File(imgPath);

if(!vFile.exists())

{

File vDirPath = vFile.getParentFile(); //new File(vFile.getParent());

vDirPath.mkdirs();

}

Uri uri = Uri.fromFile(vFile);

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);//

startActivityForResult(intent, SystemCapture);

上面我们使用的是startActivityForResult,所以最好需要重载void onActivityResult(int requestCode, int resultCode, Intent data)函数,不过因为当传入文件路径的的情况下,data返回参数是null值,只要resultCode为RESULT_OK,则上述代码中/sdcard/test/img.jpg的图片文件就是最新的照片文件。所以我们在这里只需给出如下简单的代码,将其显示到ImageView中

if (resultCode == RESULT_OK)

{

iViewPic.setImageURI(Uri.fromFile(new File(imgPath)));

}

假设不传参数MediaStore.EXTRA_OUTPUT的情况下,onActivityResult函数在resultCode为RESULT_OK的情况下,data返回的参数是经过实际拍摄照片经过缩放的图像数据,可以通过类似如下方法来打印缩放图像的尺寸

if (resultCode == RESULT_OK)

{

Bitmap bmp = (Bitmap)data.getExtras().get("data");

Log.d("Test", "bmp width:" + bmp.getWidth() + ", height:" + bmp.getHeight());

}

另外假如仅仅是调用系统照相机拍照,不关心拍照结果,则可以简单使用如下代码

Intent intent = new Intent(); //调用照相机

intent.setAction("android.media.action.STILL_IMAGE_CAMERA");

startActivity(intent);

备注:上面设置MediaStore.EXTRA_OUTPUT的方法,经过手机实测除了我们设定的路径下有照片外,在手机存储卡上也会保存一份照片,默认目录为sdcard/dcim/camera下面,我曾经尝试着想如果每次返回可以取得sdcard/dcim/camera下面的路径就好了,但是目前看来没办法直接获得,可以借助MediaStroe每次去查询最后一条照片记录,应该也是可行的。

例2、 实现摄像

在摄像功能时,尝试着设置MediaStore.EXTRA_OUTPUT以传入类似拍照时的文件路径,结果在我的测试真机上,那个视频文件居然是一个0k的空文件,最后通过类似如下代码实现

Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);

intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);//参数设置可以省略

startActivityForResult(intent, SystemVideoRecord);

在onActivityResult函数中进行如下代码调用

Uri videoUri = data.getData();

//String[] projection = { MediaStore.Video.Media.DATA, MediaStore.Video.Media.SIZE };

Cursor cursor = managedQuery(videoUri, null, null, null, null);

cursor.moveToFirst();//这个必须加,否则下面读取会报错

int num = cursor.getCount();

String recordedVideoFilePath = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));

int recordedVideoFileSize = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.SIZE));

iResultText.setText(recordedVideoFilePath);

Log.i("videoFilePath", recordedVideoFilePath);

Log.i("videoSize", ""+recordedVideoFileSize);

上面的返回参数data,也会因为用户是否设置MediaStore.EXTRA_OUTPUT参数而改变,假设没有通过EXTRA_OUTPUT设置路径,data.getData返回的Uri为content://media/external/video/media/*,*个数字,代表具体的记录号,通过managedQuery可以获取到路径,假如设置了EXTRA_OUTPUT的话(比如/sdcard/test.3gp),则data.getData返回的Uri则为file:///sdcard/test.3gp,但是该文件居然是空白内容(不知道是不是跟手机有关,也没有在其它手机上验证过)。

根据Camera API实现自己的拍照和摄像程序

通过上面对调用系统Camera App实现拍照和摄像功能的例子,我们发现虽然能够满足我们的需求,但是毕竟自由度降低了,而且拍照的界面就是系统的样子,现在很多拍照程序,比如火爆的Camera 360软件等,就需要根据SDK提供的Camera API来编写自己的程序。

准备工作

上面调用系统Camera App,我们压根不需要任何权限,但是这里用Camera API,就必须在manifest内声明使用权限,通常由以下三项

<uses-permission android:name = "android.permission.CAMERA" />

<uses-feature android:name = "android.hardware.camera" />

<uses-feature android:name = "android.hardware.camera.autofocus" />

一般拍照和摄像的时候需要写到sd卡上,所以还有一向权限声明如下

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

真做摄像功能时,需要音频录制和视频录制功能,所以又需要下面两项权限声明

<uses-permission android:name="android.permission.RECORD_VIDEO"/>

<uses-permission android:name="android.permission.RECORD_AUDIO"/>

另外使用Camera API拍照或摄像,都需要用到预览,预览就要用到SurfaceView,为此Activity的布局中必须有SurfaceView。

拍照流程

上面简单介绍了下准备工作,下面结合拍照过程中的需要用到的API对拍照流程做下简单描述

1、在Activity的OnCreate函数中设置好SurfaceView,包括设置SurfaceHolder.Callback对象和SurfaceHolder对象的类型,具体如下

SurfaceView mpreview = (SurfaceView) this.findViewById(R.id.camera_preview);

SurfaceHolder mSurfaceHolder = mpreview.getHolder();

mSurfaceHolder.addCallback(this);

mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

2、在SurfaceHolder.Callback的surfaceCreated函数中,使用Camera的Open函数开机摄像头硬件,这个API在SDK 2.3之前,是没有参数的,2.3以后支持多摄像头,所以开启前可以通过getNumberOfCameras先获取摄像头数目,再通过getCameraInfo得到需要开启的摄像头id,然后传入Open函数开启摄像头,假如摄像头开启成功则返回一个Camera对象,否则就抛出异常;

3、开启成功的情况下,在SurfaceHolder.Callback的surfaceChanged函数中调用getParameters函数得到已打开的摄像头的配置参数Parameters对象,如果有需要就修改对象的参数,然后调用setParameters函数设置进去(SDK2.2以后,还可以通过Camera::setDisplayOrientation设置方向);

4、同样在surfaceChanged函数中,通过Camera::setPreviewDisplay为摄像头设置SurfaceHolder对象,设置成功后调用Camera::startPreview函数开启预览功能,上面3,4两步的代码可以如下所示

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)

{

//已经获得Surface的width和height,设置Camera的参数

Camera.Parameters parameters = camera.getParameters();

parameters.setPreviewSize(w, h);

List<Size> vSizeList = parameters.getSupportedPictureSizes();

for(int num = 0; num < vSizeList.size(); num++)

{

Size vSize = vSizeList.get(num);

}

if(this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)

{

//如果是竖屏

parameters.set("orientation", "portrait");

//在2.2以上可以使用

//camera.setDisplayOrientation(90);

}

else

{

parameters.set("orientation", "landscape");

//在2.2以上可以使用

//camera.setDisplayOrientation(0);

}

camera.setParameters(parameters);

try {

//设置显示

camera.setPreviewDisplay(holder);

} catch (IOException exception) {

camera.release();

camera = null;

}

//开始预览

camera.startPreview();

}

5、假设要支持自动对焦功能,则在需要的情况下,或者在上述surfaceChanged调用完startPreview函数后,可以调用Camera::autoFocus函数来设置自动对焦回调函数,该步是可选操作,有些设备可能不支持,可以通过Camera::getFocusMode函数查询。代码可以参考如下:

// 自动对焦

camera.autoFocus(new AutoFocusCallback()

{

@Override

public void onAutoFocus(boolean success, Camera camera)

{

if (success)

{

// success为true表示对焦成功,改变对焦状态图像

ivFocus.setImageResource(R.drawable.focus2);

}

}

});

6、在需要拍照的时候,调用takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback)函数来完成拍照,这个函数中可以四个回调接口,ShutterCallback是快门按下的回调,在这里我们可以设置播放“咔嚓”声之类的操作,后面有三个PictureCallback接口,分别对应三份图像数据,分别是原始图像、缩放和压缩图像和JPG图像,图像数据可以在PictureCallback接口的void onPictureTaken(byte[] data, Camera camera)中获得,三份数据相应的三个回调正好按照参数顺序调用,通常我们只关心JPG图像数据,此时前面两个PictureCallback接口参数可以直接传null;

7、每次调用takePicture获取图像后,摄像头会停止预览,假如需要继续拍照,则我们需要在上面的PictureCallback的onPictureTaken函数末尾,再次掉哟更Camera::startPreview函数;

8、在不需要拍照的时候,我们需要主动调用Camera::stopPreview函数停止预览功能,并且调用Camera::release函数释放Camera,以便其他应用程序调用。SDK中建议放在Activity的Pause函数中,但是我觉得放在surfaceDestroyed函数中更好,示例代码如下

// 停止拍照时调用该方法

public void surfaceDestroyed(SurfaceHolder holder)

{

// 释放手机摄像头

camera.release();

}

以上就是自己实现拍照程序的的流程,一般还可以还可以获取预览帧的图像数据,可以分别通过Camera::setPreviewCallback和Camera::setOneShotPreviewCallback来设置每帧或下一帧图像数据的回调,这里就不做展开了。

摄像流程

摄像流程也是需要预览的,而且流程上与拍照流程在起始的1~4步流程和结束的8流程是一样的,唯一不同的是6和7两个步骤,至于5自动对焦本身就是可选的,在摄像流程也没必要。

6、开启视频录制,需要创建一个MediaRecorder对象,并调用Camera::unLock操作解锁摄像头,因为默认Camera都是锁定的,只有解锁后MediaRecorder等多媒体进程调用,并设置一些参数,然后调用MediaRecorder:: start开启录制具体可以参阅如下代码:

MediaRecorder mMediaRecorder = new MediaRecorder();

// Unlock the camera object before passing it to media recorder.

camera.unlock();

mMediaRecorder.setCamera(camera);

mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);

mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

mMediaRecorder.setProfile(mProfile);

mMediaRecorder.setMaxDuration(100000);//ms为单位

long dateTaken = System.currentTimeMillis();

Date date = new Date(dateTaken);

SimpleDateFormat dateFormat = new SimpleDateFormat(getString(R.string.video_file_name_format));

String title = dateFormat.format(date);

String filename = title + ".3gp"; // Used when emailing.

String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME;

String filePath = cameraDirPath + "/" + filename;

File cameraDir = new File(cameraDirPath);

cameraDir.mkdirs();

mMediaRecorder.setOutputFile(filePath);

try {

mMediaRecorder.prepare();

mMediaRecorder.start(); // Recording is now started

} catch (RuntimeException e) {

Log.e(TAG, "Could not start media recorder. ", e);

return;

}

7、上面设置了最大间隔为100s,当100是视频录制结束,录制就会被停止,如果没有设时长和文件大小限制,那么通常需要调用MediaRecorder:: stop函数主动停止视频的录制,并将Camera对象通过lock函数继续加锁,示例代码如下

mMediaRecorder.stop();

mMediaRecorder.reset();

mMediaRecorder.release();

mMediaRecorder = null;

if(camera != null)

camera.lock();

之后的操作根据交互要么重新录制要么就释放Camera对象回到拍照流程的8步骤了。在这里就不做赘述了。

使用和整理过程中,由于英文不太好,非常感谢网上的一篇SDK中文翻译,链接地址如下

http://blog.csdn.net/raindrophust/article/details/6205038

另外Android开发,最佳借鉴,我觉得还是源码,Camera的很多参数和使用方法可以参照源码中Camera APP的源码,目录为packages\apps\Camera。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

public class

Camera

extends Object

    本类主要用于和 camera service 建立及断开连接、设置拍照功能 、开启及关闭 预览 、拍照、检索 frames编码成 video 。本类没有默认的构造函数,你可以通过 open() 函数获得一个 Camera 对象。

       首先要使用硬件 camera ,必须要在 manifest 文件中声明使用权限,例如应用中要使用 camera 及自动对焦功能,那么 manifest 文件中包含下列几行声明:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

   通过该类实现照相功能,一般需要下列几个步骤 :

1 通过函数 open(int) 获得一个 camera 对象

2 通过函数 getParameters() 得到一个已有的 ( 默认的 ) 设置

3 如果有需要,可以通过函数 setParameters(Camera.Parameters) ,修改第二步返回的Camera.Parameters 对象 .

4 通过函数 setDisplayOrientation(int) 来设置屏幕的水平或垂直

5 重要:传递一个已经初始化好了的 SurfaceHolder 对象给函数 setPreviewDisplay(SurfaceHolder) 如果没有 surface  carema 是无法打开预览功能。

重要 : 调用函数 startPreview() 更新预览的 surface ,开始照相之前必须开启预览功能

7 通过函数 l takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback) 实现照相功能 . 在回调函数中可以得到实际的相片数据 .

8         每完成一次照相,预览功能会停止。如果要照更多像,需要再次调用 startPreview() .

9 调用 stopPreview()   停止预览 .

10 重要 : 调用 release() 以便其他应用可以方便使用 camera. 使用 camera 的应用程序应该在 onPause() (并且在 onResume() 中重新 re- open() ), 立即释放 camera.

 

按照以下步骤快速切换 video recording 模式 :

1         如上所述得到一个初始化的 Camera ,并开启预览功能 .

2         调用 unlock() 使得 media 进程可以访问 camera.

3         将 camera 传递给函数 setCamera(Camera) . 查看关于 video recording 的 MediaRecorder 信息 .

4         完成了 recording ,调用 reconnect() 来 re-acquire and re-lock the camera.

5         如果有需要,可以重新开启预览,照更多的相、录更多视频 .

6         最后如上所述调用函数 stopPreview() and release() 来停止预览 .

     这个类不是线程安全的,这意味着是通过event thread使用该类。在绝大多数需要长时间运行的操作(预览、聚焦、照相等)都是非同步的,只要有需求就会立刻唤醒相关回调函数。而这些回调函数是由调用 open(int)的event thread来调用的。故这些类方法一定不能同时在多个线程中运行。

      注意:不同性能的android设备有不同的硬件规格,如兆像素等级和自动对焦性能,为了使你的应用和更多设备兼容,最好不要限制camera规格。

 

P ublic Methods 
public final void addCallbackBuffer (byte[] callbackBuffer) 
Since: API Level 8 
     给callback buffer queue添加一个已分配好内存的buffer。应用程序可以添加一个或多个buffers到该队列中. 当一个preview frame产生并且该队列还有至少一个可用的buffer,那么该buffer将被移除队列使用。这时会唤醒preview callback。如果preview frame产生但是该队列中没有可用的buffer,那么这个frame就会被丢弃。应用程序应该在处理完buffer中数据后,再将buffer重新添加进队列。
     Buffer的大小是由该preview image的宽,高,及每个像素的bytes三者的乘积来决定的. 通过函数getPreviewSize()来得到该preview image的 width and height.通过函数getBitsPerPixel(int) / 8可以得到每个像素包含的 Bytes ,通过函数getPreviewFormat() 可以得到该image采用的格式. 
     只有通过函数setPreviewCallbackWithBuffer(PreviewCallback)设置预览回调的时候,才会用到本函数。当通过函数setPreviewCallback(PreviewCallback) 或setOneShotPreviewCallback(PreviewCallback)设置预览回调时,所需的buffer由系统自动分配。
Parameters
 
callbackBuffer,添加到队列中的buffer。该buffer的大小应该是width * height * bits_per_pixel / 8.

 

public final void autoFocus (Camera.AutoFocusCallback cb)

Since: API Level 1

打开 camera 的自动对焦功能并且注册一个当 camera 对焦时的回调函数。这个函数只在 preview 激活的时候有效 ( 即在startPreview() and before stopPreview() 之间。

调用者应该通过函数 getFocusMode()   来查看是否可以使用 autoFocus() 函数,如果 camera 并不支持 auto-focus, 那么该函数不做任何处理,立即调用 onAutoFocus(Boolean ,Camera) 函数。如果你的应用不能安装在没有自动对焦的设备上,你需要在你的应用程序中通过 <uses-feature>manifest 元素声明需要使用自动对焦功能。

如果当前的 flash mode 不是 FLASH_MODE_OFF , flash 将在自动对焦过程中启动,具体依赖于驱动及 camera 硬件。

public final void cancelAutoFocus ()

Since: API Level 5

取消任何当前正在运行的 auto-focus. 该方法将 focus position 重置为默认的值。如果 camera 不支持 auto-focus ,该方法不做任何操作。

See Also

autoFocus(Camera.AutoFocusCallback)

public static void getCameraInfo (int cameraId, Camera.CameraInfo cameraInfo)

Since: API Level 9

返回某一特定 camera 的信息

如果 getNumberOfCameras() 返回 N ,有效 id 从 0 到 N-1 。

public static int getNumberOfCameras ()

Since: API Level 9

返回本设备上的所有可用的物理 camera 个数

public Camera.Parameters getParameters ()

Since: API Level 1

返回当前 Camera service 的设置,如果要修改参数,必须将返回的 Parameters 对象传递给函数setParameters(Camera.Parameters) 实现 .

See Also

setParameters(Camera.Parameters)

public final void lock ()

Since: API Level 5

Re-locks the camera to prevent other processes from accessing it. Camera objects are locked by default unlessunlock() is called. Normally reconnect() is used instead.

If you are not recording video, you probably do not need this method.

给 camera 加锁以防止其他进程的访问,默认情况下 camera 是被锁的,除非调用 unlock() 函数解锁。通常可以通过函数 reconnect() 代替。如果你不需要 recording viedo 功能,你不需要使用该方法。

Throws

RuntimeException

if the camera cannot be re-locked (for example, if the camera is still in use by another process).

public static Camera open (int cameraId)

Since: API Level 9

创建一个新的 camera 对象以使用 camera 硬件

当你使用了 camera 后,一定要调用 release(), 否则 camera 将被一直锁住,无法被其他应用程序使用。

应用程序同时只能存在一个激活的 camera

其他方法的 callback 函数会传递给调用 open() 函数的线程的 event loop 。如果该线程没有 event loop ,那么回调函数就会被传递给 main application event loop ,如果没有 main application event loop , callback 函数不会传递

注意 : 在一些设备上,该方法会运行很长一段时间,最好是在一个worker 线程上调用该函数( (possibly using AsyncTask )以避免阻塞 main application UI thread.

Parameters

cameraId

the hardware camera to access, between 0 and getNumberOfCameras() -1.

Returns

返回一个 connected locked 并 ready for use 的 Camera objecte.

Throws

RuntimeException

if connection to the camera service fails (for example, if the camera is in use by another process).

public static Camera open ()

Since: API Level 1

创建一个新的访问设备上第一个 back-facing camera 的 Camera 类对象,如果设备没有 back-facing camera ,则该函数返回 null 。

See Also

open(int)

public final void reconnect ()

Since: API Level 8

在另一个进程使用之后,重新与 camera 建立连接。进程 unlock() 之后,该进程可能仍在使用 camera( 这里理解不知是否恰当 ) ,当其使用完毕后,你一定要与 camera 重新建立连接,这样可重新获得锁以继续使用 camera 。

如果调用了 setCamera(Camera) ,该接口一定要在 MediaRecorder 之后调用。

当然如果你不需要使用 recording video ,你不用使用该函数

 

Throws

IOException

if a connection cannot be re-established (for example, if the camera is still in use by another process).

public final void release ()

Since: API Level 1

断开和释放 Camera 对象资源,当使用完了 camera ,你要尽快调用该函数。

public final void setDisplayOrientation (int degrees)

Since: API Level 8

设置 preview 的顺时针旋转角度。这将影响 preview frames 和拍照之后的相片显示。该方法主要用于垂直模式的应用。注意在旋转之前, front-facing cameras 的 preview 显示是水平 flip 的,这就是说, image 是沿着 camera sensor 的垂直中心轴来反射的 (无法理解其意思)。所以用户可以像照镜子一样看到他们自己。这不会影响传入函数onPreviewFrame(byte[], Camera) 的、 JPEG 相片的、或记录的 video 的 byte array 的顺序。在preview 期间是不允许调用该方法的。如果你想要是你的照片和显示出来的角度一致,你可以参考下列代码:

 

  public static voidsetCameraDisplayOrientation ( Activityactivity , 
         
 int cameraId , android .hardware . Camera camera ) { 
     android
 . hardware . Camera .CameraInfo info = 
             
 new android . hardware .Camera . CameraInfo (); 
     android
 . hardware . Camera .getCameraInfo ( cameraId , info ); 
     
 int rotation = activity .getWindowManager (). getDefaultDisplay() 
             
 . getRotation (); 
     
 int degrees = 0 ; 
     
 switch ( rotation ) { 
         
 case Surface . ROTATION_0 :degrees = 0 ; break ; 
         
 case Surface . ROTATION_90 :degrees = 90 ; break ; 
         
 case Surface . ROTATION_180 :degrees = 180 ; break ; 
         
 case Surface . ROTATION_270 :degrees = 270 ; break ; 
     
 } 

     
 int result ; 
     
 if ( info . facing == Camera .CameraInfo . CAMERA_FACING_FRONT ) { 
         result 
= ( info . orientation+ degrees ) % 360 ; 
         result 
= ( 360 - result ) % 360;   // compensate the mirror 
     
 } else {   // back-facing 
         result 
= ( info . orientation- degrees + 360 ) % 360 ; 
     
 } 
     camera
 . setDisplayOrientation (result ); 
 
 } 
 

Parameters

degrees

the angle that the picture will be rotated clockwise. Valid values are 0, 90, 180, and 270. The starting position is 0 (landscape).

See Also

·     setPreviewDisplay(SurfaceHolder)

public final void setErrorCallback (Camera.ErrorCallback cb)

Since: API Level 1

Registers a callback to be invoked when an error occurs.

Parameters

cb

The callback to run

public final void setOneShotPreviewCallback (Camera.PreviewCallback cb)

Since: API Level 3

Installs a callback to be invoked for the next preview frame in addition to displaying it on the screen. 一次调用后,该回调函数就会被清除,该函数可在任何时候调用,即使是正在预览,调用该函数将覆盖以前的回调。

Parameters

cb

a callback object that receives a copy of the next preview frame, or null to stop receiving callbacks.

public void setParameters (Camera.Parameters params)

Since: API Level 1

Changes the settings for this Camera service.

Parameters

params

the Parameters to use for this Camera service

Throws

RuntimeException

if any parameter is invalid or not supported.

See Also

·     getParameters()

public final void setPreviewCallback (Camera.PreviewCallback cb)

Since: API Level 1

该函数为每个 preview frame 安装一个 callback ,并将每个 preview frame 显示到屏幕上,只要 preview 处在激活状态,这些回调函数就会被重复调用 . 该方法可以在任何时候调用,即使 preview is live. 调用该函数将覆盖一起设置的其他的回调.

Parameters

cb

a callback object that receives a copy of each preview frame, or null to stop receiving callbacks.

public final void setPreviewCallbackWithBuffer (Camera.PreviewCallback cb)

Since: API Level 8

安装一个会被每个 preview frame 激活的回调函数,这些回调函数使用由 addCallbackBuffer(byte[]) 提供的 buffer ,并将每个 preview frame 显示到屏幕上。只要 preview 是激活的 buffer 是足够的,这些回调就会不断重复被调用 , 并覆盖其他的回调。

该方法目的是要通过复用 preview frame memory 来提高 preview 的性能和帧率。在调用该方法前后或没有回调注册时,需要调用函数 addCallbackBuffer(byte[]) . 如果传一个空的 callback 给该函数,那么 buffer queue 将被清除 . 将调用 setPreviewCallback(Camera.PreviewCallback) setOneShotPreviewCallback(Camera.PreviewCallback) .

Parameters

cb

获得了 preview frame 数据拷贝的回调对象,如果 cb 为空,该函数将停止接受 callbacks 并清空 buffer queue.

See Also

·     addCallbackBuffer(byte[])

public final void setPreviewDisplay (SurfaceHolder holder)

Since: API Level 1

为 live preview 设置 surface ,对于 preview , surface 是必要 ; 对于拍照 preview 是必要的。相同的 surface 可以被无损重置。

在调用该方法时 SurfaceHolder 必须已经包含了一个 surface. 如果使用 SurfaceView ,必须通过函数addCallback(SurfaceHolder.Callback) 注册一个 SurfaceHolder.Callback 并且在调用 setPreviewDisplay() 或开启 preview. 之前,等待 surfaceCreated(SurfaceHolder)  

在调用 startPreview() 函数之前,必须调用该函数。不过有一个例外,那就是如果调用 startPreview() 之前,没有设置 preview surface 或者设为 null ,该函数可能被传入一个非空 parameter ,调用一次已设置的 preview surface (这就是得 camera 的启动和 surface 的创建可以并行,节省了时间 ) ,在 preview 运行的时候,这个 preview surface 不可更改。 .

Parameters

holder

包含放置 preview 的 surface ,可能为空以移除原来的 preview surface

Throws

IOException

if the method fails (for example, if the surface is unavailable or unsuitable).

public final void setZoomChangeListener (Camera.OnZoomChangeListener listener)

Since: API Level 8

Registers a listener to be notified when the zoom value is updated by the camera driver during smooth zoom.

设置监听器监听 smooth zoom 期间, camera 驱动对 zoom value 的值的更改

Parameters

listener

the listener to notify

See Also

·     startSmoothZoom(int)

public final void startPreview ()

Since: API Level 1

开始捕捉和绘制 preview frames 到屏幕上。当然 preveiw 并没有真正开启,直到通过函数setPreviewDisplay(SurfaceHolder) 得到 a surface.

如果调用了 setPreviewCallback(Camera.PreviewCallback) ,setOneShotPreviewCallback(Camera.PreviewCallback) , 或setPreviewCallbackWithBuffer(Camera.PreviewCallback) , 当框架发现 preview data可用时会自动调用回调函数 onPreviewFrame(byte[], Camera) 

public final void startSmoothZoom (int value)

Since: API Level 8

该函数使相机平滑变焦到 value 值 . 驱动会时时通知 Camera.OnZoomChangeListener zoom 值及是否已经停止变焦了 . 例如当前的 zoom 是 0 ,设置 value 为 3 然后调用 startSmoothZoom. 那么函数onZoomChange(int, boolean, Camera)   会被调用三次,分别传入 zoom 值为 1, 2, and 3. 应用程序也可以提前调用函数 stopSmoothZoom() 来停止变焦 . 在停止变焦之前,不能再次调用 startSmoothZoom 函数或更改 zoom 值 . 如果提供的目标 zoom 值和当前 zoom 值一致了,就不会在调用回调函数。通过函数isSmoothZoomSupported() 测试硬件是否支持变焦,如果返回值为 true ,说明支持,则可以使用本函数实现变焦 .

Parameters

value

zoom value. The valid range is 0 to getMaxZoom() .

Throws

IllegalArgumentException

if the zoom value is invalid.

RuntimeException

if the method fails.

See Also

·    setZoomChangeListener(OnZoomChangeListener)

public final void stopPreview ()

Since: API Level 1

停止拍照,停止将预览帧绘制到 surface 上,并且重置 camera ,以备下次 startPreview() .

public final void stopSmoothZoom ()

Since: API Level 8

停止平稳变焦。应用程序可以设置 Camera.OnZoomChangeListener 监听器来监听 zoom 的停止 . 同样如果函数 isSmoothZoomSupported() 返回 true ,表示硬件支持变焦,可以调用本函数。 .

Throws

RuntimeException

if the method fails.

public final void takePicture (Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallbackjpeg)

Since: API Level 1

与 takePicture(shutter, raw, null, jpeg) 等效 .

See Also

·     takePicture(ShutterCallback, PictureCallback, PictureCallback, PictureCallback)

public final void takePicture (Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallbackpostview, Camera.PictureCallback jpeg)

Since: API Level 5

触发一次非同步拍照, camera service 将按照拍照的流程为应用完成一系列的回调初始化。 shutter callback ,拍照之后会调用该回调 . 该函数中可以触发一个声音,提示用户拍照完成。 The raw callback occurs ,当 raw image data 有效的时候,会触发该回调 ( 注意 : 如果没有足够的 memory 用来放置拷贝,该值可能为 ). The postview callback , 当生成了经过缩放、简单处理的图片的时候,调用 postview callback 回调 ( 注意:并不是所有的硬件都支持该功能 ) 。 The jpeg callback ,当压缩的图片数据有效的时候,会调用该回到接口。对于这些参数,如果没有需要,可以直接传递 null 即可 .

当然这些回调方法,都必须在 preview 是激活的 ( 即在函数 startPreview() 调用之后 ). 完成拍照之后, preview会停止,这个时候如果你想要再次开开 preview ,拍摄更多的照片,你需要重新调用 startPreview() .

.

Parameters

shutter

the callback for image capture moment, or null

raw

the callback for raw (uncompressed) image data, or null

postview

callback with postview image data, may be null

jpeg

the callback for JPEG image data, or null

public final void unlock ()

Since: API Level 5

为 camera 解锁,使得其他进程可以访问 camera. 一般地 , 直到调用函数 release() , camera 都是被包含激活的camera 对象的进程锁住的 . 如果要在进程间快速还手 , 你可以调用该函数快速释放 camera 对象给其他进程使用 ; 同样如果别的进程释放了 camera ,你可以调用函数 reconnect() 重新获取 camera.

在调用 setCamera(Camera) . 之前,你必须调用该函数。

如果你不使用 recording video ,可能你不需要用到该函数。

Throws

RuntimeException

if the camera cannot be unlocked.


-----------------------------------------------------------------------------------------------------------------------------------------------------------------

Android获取摄像头详细信息

 2011-01-05 10:15:26 来源:WEB开发网 【 减小字体  增大字体 】  关注杨恒飞的微博

核心提示: 如何获取Android设备上的详细的摄像头信息呢? 目前Samsung的Galaxy Tab和Nexus S均有前置摄像头,获取Android摄像头的详细信息,Android获取摄像头详细信息,在Android 2.3 SDK中得到了增强:在android.hardware.Camera类中,API Level 9的S

如何获取Android设备上的详细的摄像头信息呢? 目前Samsung的Galaxy Tab和Nexus S均有前置摄像头,获取Android摄像头的详细信息,在Android 2.3 SDK中得到了增强:

在android.hardware.Camera类中,API Level 9的SDK中加入了两个比较重要的方法,使用getNumberOfCameras这个static类型方法可以获取当前Android设备上的摄像头数 量,比如Nexus S有两个,方法原型如下

[java] view plaincopy
  1. public static int getNumberOfCameras ()  

而对于具体的每个摄像头的信息,可以通过Camera类的getCameraInfo()这个静态方法获取,该方法有两个参数,参数一的ID,我们 通过getNumberOfCameras获取的值减1即可,类似数组索引从0开始一样,用循环遍历每个摄像头信息,参数二是 android.hardware.Camera.CameraInfo类,有关getCameraInfo方法的原型如下:

[java] view plaincopy
  1. public static void getCameraInfo (int cameraId, Camera.CameraInfo cameraInfo)  

对于Camera.CameraInfo类而言,比较简单,包含两个字段

public int facing 代表摄像头的方位,目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置
public int orientation下面是拍照的旋转方向,一般自然些有0度、90度、180度和270度,这样可以获取我们正确的手握设备是横着还是竖着,有关拍照时的方向设置,可以参考下面的代码设置

[java] view plaincopy
  1. public static void setCameraDisplayOrientation(Activity activity,<br>  
  2.     int cameraId, android.hardware.Camera camera) {<br>  
  3.     android.hardware.Camera.CameraInfo info =<br>  
  4.     new android.hardware.Camera.CameraInfo();<br>  
  5.     android.hardware.Camera.getCameraInfo(cameraId, info);<br>  
  6.     int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();<br>  
  7.     int degrees = 0;<br>  
  8.     switch (rotation) {<br>  
  9.         case Surface.ROTATION_0: degrees = 0break;<br>  
  10.         case Surface.ROTATION_90: degrees = 90break;<br>  
  11.         case Surface.ROTATION_180: degrees = 180break;<br>  
  12.         case Surface.ROTATION_270: degrees = 270break;<br>  
  13.     }<br>  
  14. <br>  
  15.     int result;<br>  
  16.     if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {<br>  
  17.         result = (info.orientation + degrees) % 360;<br>  
  18.         result = (360 - result) % 360;// compensate the mirror<br>  
  19.     } else {// back-facing<br>  
  20.         result = (info.orientation - degrees + 360) % 360;<br>  
  21.     }<br>  
  22.     camera.setDisplayOrientation(result);<br>  
  23. }  

原创粉丝点击