Android中使用Camera类编写手机拍照App的实例教程
camera是android摄像头硬件的相机类,位于硬件包"android.hardware.camera"下。它主要用于摄像头捕获图片、启动/停止预览图片、拍照、获取视频帧等,它是设备本地的服务,负责管理设备上的摄像头硬件。
camera既然用于管理设备上的摄像头硬件,那么它也为开发人员提供了相应的方法,并且这些方法大部分都是native的,用c++在底层实现,下面简单介绍一下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硬件,使其他应用可以访问。
上面已经介绍了camera的常用方法,下面根据这些方法详细讲解android下使用camera开发拍照应用最基本的过程:
- 使用open()方法获取一个camera对象,鉴于android设备可能配置了多个摄像头,open()方法可以通过摄像头id开启指定的摄像头。
- 为camera对象设置预览类,它是一个surfaceholder对象,通过setpreviewdisplay(surfaceholder)方法设置。
- 调用startpreview()方法开始camera对象的预览。
- 调用takepicture()方法进行拍照,其中可以通过camera.picturecallback()回调获得拍摄的image数据。
- 当拍摄完成后,需要调用stoppreview()方法停止预览,并使用release()释放camera占用的资源。
以上介绍的步骤都是最基本的过程,是必不可少的。camera没有提供公开的构造函数,只能通过open()方法获取,并且必须设置一个预览类surfaceholder,如果不设置的话,将无法使用camera。在使用完成camera之后,必须使用release()释放camera资源。
实例:
使用camera控制拍照的几个步骤:
1、调用camera的open()打开相机
2、调用camera的getparameters()获取拍照参数。该方法返回一个camera.paremeters对象
3、调用camera.parameters对象方法设置拍照的参数
4、调用camera.startpreview()方法开始预览取景,在预览取景之前需要调用camera的setpreviewdisplay(surfaceholder holder)方法设置使用哪个surfaceview来显示取景图片。
5、调用camera的takepicture()方法进行拍照
6、结束程序时,调用camera的stoppreview()结束取景预览,并调用release()方法释放资源
代码:
<uses-permission android:name="android.permission.camera"/> <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".mainactivity" > <surfaceview android:id="@+id/sview" android:layout_width="match_parent" android:layout_height="wrap_content"/> <button android:id="@+id/take" android:layout_alignparentbottom="true" android:onclick="capture" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/take"/> </relativelayout> <?xml version="1.0" encoding="utf-8"?> <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <edittext android:id="@+id/photonmae" android:layout_width="match_parent" android:layout_height="wrap_content"/> <imageview android:id="@+id/show" android:layout_below="@id/photonmae" android:layout_width="match_parent" android:layout_height="wrap_content"/> </relativelayout>
package com.android.xiong.cameratest; import java.io.file; import java.io.fileoutputstream; import java.io.ioexception; import android.app.activity; import android.app.alertdialog; import android.content.dialoginterface; import android.graphics.bitmap; import android.graphics.bitmap.compressformat; import android.graphics.bitmapfactory; import android.graphics.imageformat; import android.hardware.camera; import android.hardware.camera.autofocuscallback; import android.hardware.camera.picturecallback; import android.hardware.camera.shuttercallback; import android.os.bundle; import android.os.environment; import android.util.displaymetrics; import android.view.display; import android.view.menu; import android.view.surfaceholder; import android.view.surfaceholder.callback; import android.view.layoutinflater; import android.view.surfaceview; import android.view.view; import android.view.window; import android.view.windowmanager; import android.widget.edittext; import android.widget.imageview; public class mainactivity extends activity { surfaceview sview; surfaceholder surfacehodler; int screenwidth, screenheight; // 定义系统所用的照相机 camera camera; // 是否存在预览中 boolean ispreview = false; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); // 设置全屏 requestwindowfeature(window.feature_no_title); getwindow().setflags(windowmanager.layoutparams.flag_fullscreen, windowmanager.layoutparams.flag_fullscreen); setcontentview(r.layout.activity_main); // 获取窗口管理器 windowmanager wm = getwindowmanager(); display display = wm.getdefaultdisplay(); displaymetrics metrics = new displaymetrics(); // 获取屏幕的宽和高 display.getmetrics(metrics); screenwidth = metrics.widthpixels; screenheight = metrics.heightpixels; sview = (surfaceview) findviewbyid(r.id.sview); // 设置surface不需要自己的维护缓存区 sview.getholder().settype(surfaceholder.surface_type_push_buffers); // 获得surfaceview的surfaceholder surfacehodler = sview.getholder(); // 为srfaceholder添加一个回调监听器 surfacehodler.addcallback(new callback() { @override public void surfacedestroyed(surfaceholder arg0) { // 如果camera不为null,释放摄像头 if (camera != null) { if (ispreview) camera.stoppreview(); camera.release(); camera = null; } } @override public void surfacecreated(surfaceholder arg0) { // 打开摄像头 initcamera(); } @override public void surfacechanged(surfaceholder arg0, int arg1, int arg2, int arg3) { } }); } private void initcamera() { if (!ispreview) { // 此处默认打开后置摄像头 // 通过传入参数可以打开前置摄像头 camera = camera.open(); camera.setdisplayorientation(90); } if (!ispreview && camera != null) { camera.parameters parameters = camera.getparameters(); // 设置预览照片的大小 parameters.setpreviewsize(screenwidth, screenheight); // 设置预览照片时每秒显示多少帧的最小值和最大值 parameters.setpreviewfpsrange(4, 10); // 设置照片的格式 parameters.setpictureformat(imageformat.jpeg); // 设置jpg照片的质量 parameters.set("jpeg-quality", 85); // 设置照片的大小 parameters.setpicturesize(screenwidth, screenheight); // 通过surfaceview显示取景画面 try { camera.setpreviewdisplay(surfacehodler); } catch (ioexception e) { // todo auto-generated catch block e.printstacktrace(); } // 开始预览 camera.startpreview(); ispreview = true; } } public void capture(view source) { if (camera != null) { // 控制摄像头自动对焦后才拍摄 camera.autofocus(autofocuscallback); } } autofocuscallback autofocuscallback = new autofocuscallback() { @override public void onautofocus(boolean arg0, camera arg1) { if (arg0) { // takepicture()方法需要传入三个监听参数 // 第一个监听器;当用户按下快门时激发该监听器 // 第二个监听器;当相机获取原始照片时激发该监听器 // 第三个监听器;当相机获取jpg照片时激发该监听器 camera.takepicture(new shuttercallback() { @override public void onshutter() { // 按下快门瞬间会执行此处代码 } }, new picturecallback() { @override public void onpicturetaken(byte[] arg0, camera arg1) { // 此处代码可以决定是否需要保存原始照片信息 } }, myjpegcallback); } } }; picturecallback myjpegcallback = new picturecallback() { @override public void onpicturetaken(byte[] data, camera camera) { // 根据拍照所得的数据创建位图 final bitmap bm = bitmapfactory.decodebytearray(data, 0, data.length); // 加载布局文件 view savedialog = getlayoutinflater().inflate(r.layout.save, null); final edittext potoname = (edittext) savedialog .findviewbyid(r.id.photonmae); // 获取savedialog对话框上的imageview组件 imageview show = (imageview) savedialog.findviewbyid(r.id.show); // 显示刚刚拍得的照片 show.setimagebitmap(bm); // 使用alertdialog组件 new alertdialog.builder(mainactivity.this) .setview(savedialog) .setnegativebutton("取消", null) .setpositivebutton("保存", new dialoginterface.onclicklistener() { @override public void onclick(dialoginterface arg0, int arg1) { // 创建一个位于sd卡上的文件 file file = new file(environment .getexternalstoragedirectory() + "/" + potoname.gettext().tostring() + ".jpg"); fileoutputstream fileoutstream=null; try { fileoutstream=new fileoutputstream(file); //把位图输出到指定的文件中 bm.compress(compressformat.jpeg, 100, fileoutstream); fileoutstream.close(); } catch (ioexception io) { io.printstacktrace(); } } }).show(); //重新浏览 camera.stoppreview(); camera.startpreview(); ispreview=true; } }; @override public boolean oncreateoptionsmenu(menu menu) { getmenuinflater().inflate(r.menu.main, menu); return true; } }