- 浏览: 720214 次
- 性别:
- 来自: 大连
文章分类
最新评论
-
xuelj:
我的Android进阶之旅------>Android使用9Patch图片作为不失真背景 -
lBovinl:
,浩瀚~
我的Android进阶之旅------>经典的大客推荐(排名不分先后)!! -
xyy_zero:
看着听犀利的,大神,有demo吗?可以分享下不。我最近需要开发 ...
给android设备增加串口功能
android之相机开发
在android中应用相机功能,一般有两种:一种是直接调用系统相机,一种自己写的相机。
我将分别演示两种方式的使用:
第一种:是使用Intent跳转到系统相机,action为:android.media.action.STILL_IMAGE_CAMERA
关键代码:
Intent intent = new Intent(); //调用照相机 intent.setAction("android.media.action.STILL_IMAGE_CAMERA"); startActivity(intent);
例子:
import android.app.Activity; import android.content.Intent; import android.os.Bundle; public class CameraTest_2 extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Intent intent = new Intent(); //调用照相机 intent.setAction("android.media.action.STILL_IMAGE_CAMERA"); startActivity(intent); } }
想要测试的,可以直接新建一个项目,并且把主activity的代码换成上面的,然后运行,我测试了一下,上面这个代码并不
需要权限,毕竟只是调用系统自带的程序。
当然网上还有一些其他相关的调用方法,只要设置对了action,那么系统就会调用系统自带的相机.
第二种:
(1)首先我们要自己创建一个照相界面,必须考虑用什么控件显示照相机中的预览效果,显然android已经帮我们做好了选择,那就是SurfaceView
控制SurfaceView需要一个surfaceHolder,他是系统提供的一个用来设置SurfaceView的一个对象,可以通过surfaceView.getHolder()这个方法来获得.
Camera提供一个setPreviewDisplay(SurfaceHolder)的方法来连接surfaceHolder,并通过他来控制surfaceView.
而我们则使用android的Camera类提供了startPreview()和stopPreview()来开启和关闭预览.
关系如下:
Camera -- -->SurfaceHolder------>SurfaceView.
(2)知道怎么预览了,当然也要知道怎么开启相机.Camera.open()这是个静态方法,如果相机没有别人用着,则会返回一个 相机引用,如果被人用着,则会抛出异常。很奇怪的是,这个方法,不能随便放,如放在构造方法或者onCreate()方法中,都会照成没有预览效果.
(3)
SurfaceHolder.Callback,这是个holder用来显示surfaceView 数据的接口,他分别必须实现3个方法
surfaceCreated()这个方法是surface 被创建后调用的
surfaceChanged()这个方法是当surfaceView发生改变后调用的
surfaceDestroyed()这个是当surfaceView销毁时调用的.
surfaceHolde通过addCallBack()方法将响应的接口绑定到他身上.
surfaceHolder还必须设定一个setType()方法,查看api的时候,发现这个方法已经过时,但是不写,又会报错
(4)
我用以上知识写了一个MySurfaceView类,他继承于SurfaceView,并在里面实现了照相机的预览功能.这个我觉得最简单的照相机预览代码:
MySurfaceView.java:
import java.io.IOException; import android.content.Context; import android.graphics.PixelFormat; import android.hardware.Camera; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback{ SurfaceHolder holder; Camera myCamera; public MySurfaceView(Context context) { super(context); holder = getHolder();//获得surfaceHolder引用 holder.addCallback(this); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型 } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub if(myCamera == null) { myCamera = Camera.open();//开启相机,不能放在构造函数中,不然不会显示画面. try { myCamera.setPreviewDisplay(holder); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { myCamera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub myCamera.stopPreview();//停止预览 myCamera.release();//释放相机资源 myCamera = null; Log.d("ddd", "4"); } }
主activity代码:
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; public class CameraTest_3 extends Activity { /** Called when the activity is first created. */ MySurfaceView mySurface; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mySurface = new MySurfaceView(this); setContentView(mySurface); } }
而且必须给应用添加权限:
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
(5)能够预览了,接下来就是拍照了,拍照用到了一个camera.tackPiture()这个方法,这个方法,有三个参数分别是
ShutterCallBack shutter,PictureCallBack raw,PictureCallBack jpeg.
下面是对他们的实现
private ShutterCallback shutter = new ShutterCallback() { @Override public void onShutter() { // TODO Auto-generated method stub Log.d("ddd", "shutter"); } }; private PictureCallback raw = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // TODO Auto-generated method stub Log.d("ddd", "raw"); } }; private PictureCallback jpeg = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // TODO Auto-generated method stub Log.d("ddd","jpeg"); } };
当开始拍照时,会依次调用shutter的onShutter()方法,raw的onPictureTaken方法,jpeg的onPictureTaken方法.
三个参数的作用是shutter--拍照瞬间调用,raw--获得没有压缩过的图片数据,jpeg---返回jpeg的图片数据
当你不需要对照片进行处理,可以直接用null代替.
注意,当调用camera.takePiture方法后,camera关闭了预览,这时需要调用startPreview()来重新开启预览。
我用以上知识,加到上面的那个例子,就形成了下面的代码:
MySurfaceView.java:
package jason.camera; import java.io.IOException; import android.content.Context; import android.graphics.PixelFormat; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.hardware.Camera.ShutterCallback; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback{ SurfaceHolder holder; Camera myCamera; private ShutterCallback shutter = new ShutterCallback() { @Override public void onShutter() { // TODO Auto-generated method stub Log.d("ddd", "shutter"); } }; private PictureCallback raw = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // TODO Auto-generated method stub Log.d("ddd", "raw"); } }; private PictureCallback jpeg = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // TODO Auto-generated method stub Log.d("ddd","jpeg"); } }; public MySurfaceView(Context context) { super(context); holder = getHolder();//获得surfaceHolder引用 holder.addCallback(this); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型 } public void tackPicture() { myCamera.takePicture(null,null,null); } public void voerTack() { myCamera.startPreview(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { myCamera.startPreview(); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub if(myCamera == null) { myCamera = Camera.open();//开启相机,不能放在构造函数中,不然不会显示画面. try { myCamera.setPreviewDisplay(holder); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub myCamera.stopPreview();//停止预览 myCamera.release();//释放相机资源 myCamera = null; } }
主activity:
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; public class CameraTest_3 extends Activity implements OnClickListener { /** Called when the activity is first created. */ MySurfaceView mySurface; boolean isClicked = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mySurface = new MySurfaceView(this); setContentView(mySurface); mySurface.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub if(!isClicked) { mySurface.tackPicture(); isClicked = true; }else { mySurface.voerTack(); isClicked = false; } }
这样就是实现了拍照的功能,那么怎样要图片保存呢?那么这是就需要在那个参数中的jpeg的
方法里面进行处理了,那个方法的data参数,就是相片的数据。
我们通过BitmapFactory.decodeByteArray(data, 0, data.length)来获得图片并通过io处理,将图片保存到想要保存的位置
下面这段代码,是将照片保存到/sdcard/wjh.jpg;并把一些没有用到的代码全部删掉,剩下一些必须的代码
package java.camera; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PixelFormat; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.hardware.Camera.ShutterCallback; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback{ SurfaceHolder holder; Camera myCamera; private PictureCallback jpeg = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // TODO Auto-generated method stub try { Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length); File file = new File("/sdcard/wjh.jpg"); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); bm.compress(Bitmap.CompressFormat.JPEG,100,bos); bos.flush(); bos.close(); }catch(Exception e) { e.printStackTrace(); } } }; public MySurfaceView(Context context) { super(context); holder = getHolder();//获得surfaceHolder引用 holder.addCallback(this); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型 } public void tackPicture() { myCamera.takePicture(null,null,jpeg); } public void voerTack() { myCamera.startPreview(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { myCamera.startPreview(); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub if(myCamera == null) { myCamera = Camera.open();//开启相机,不能放在构造函数中,不然不会显示画面. try { myCamera.setPreviewDisplay(holder); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub myCamera.stopPreview();//停止预览 myCamera.release();//释放相机资源 myCamera = null; } }
注意,这是必须添加在sd卡上写数据的权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
(7)能够拍照了,这下子要考虑如何让图片更好看了,这显然是专业人士的强项,但是我们在程序上,也可以做一些处理,
向上面的那些,因为我直接把surfaceView当做整体布局,就可能出现屏幕被拉开了,不是很好看,所以这时,就可以不要把
surfaceView弄成整体布局,把他弄到一个布局管理器,再设置相关的参数.
这时需要注意的是有些参数不能随便乱设
如以下代码:
Camera.Parameters parames = myCamera.getParameters();//获得参数对象 parames.setPictureFormat(PixelFormat.JPEG);//设置图片格式 parames.setPreviewSize(640,480);//这里面的参数只能是几个特定的参数,否则会报错.(176*144,320*240,352*288,480*360,640*480) myCamera.setParameters(parames);
还有自动对焦,当然有些手机没有这个功能,自动对焦是通过autoFocus()这个方法调用一个自动对焦的接口,并在里面进行处理。
注意,这个方法必须在startPreview()和stopPreview()中间。
AutoFocusCallback是自动对焦的接口,实现它必须实现public void onAutoFocus(boolean success, Camera camera)这个方法,
所以我们可以将拍照方法放在这里面,然后对焦后再进行拍摄。。效果会好很多。
注意自动对焦需要添加
<uses-feature android:name="android.hardware.camera.autofocus" />
下面是主要代码,直接贴出来了
import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.app.Activity; import android.content.pm.ActivityInfo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PixelFormat; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.PictureCallback; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.view.SurfaceHolder.Callback; import android.view.View.OnClickListener; public class CameraTest_4 extends Activity implements Callback, OnClickListener, AutoFocusCallback{ SurfaceView mySurfaceView;//surfaceView声明 SurfaceHolder holder;//surfaceHolder声明 Camera myCamera;//相机声明 String filePath="/sdcard/wjh.jpg";//照片保存路径 boolean isClicked = false;//是否点击标识 //创建jpeg图片回调数据对象 PictureCallback jpeg = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // TODO Auto-generated method stub try {// 获得图片 Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length); File file = new File(filePath); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);//将图片压缩到流中 bos.flush();//输出 bos.close();//关闭 }catch(Exception e) { e.printStackTrace(); } } }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);//无标题 //设置拍摄方向 this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); setContentView(R.layout.main); //获得控件 mySurfaceView = (SurfaceView)findViewById(R.id.surfaceView1); //获得句柄 holder = mySurfaceView.getHolder(); //添加回调 holder.addCallback(this); //设置类型 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //设置监听 mySurfaceView.setOnClickListener(this); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub //设置参数并开始预览 Camera.Parameters params = myCamera.getParameters(); params.setPictureFormat(PixelFormat.JPEG); params.setPreviewSize(640,480); myCamera.setParameters(params); myCamera.startPreview(); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub //开启相机 if(myCamera == null) { myCamera = Camera.open(); try { myCamera.setPreviewDisplay(holder); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub //关闭预览并释放资源 myCamera.stopPreview(); myCamera.release(); myCamera = null; } @Override public void onClick(View v) { // TODO Auto-generated method stub if(!isClicked) { myCamera.autoFocus(this);//自动对焦 isClicked = true; }else { myCamera.startPreview();//开启预览 isClicked = false; } } @Override public void onAutoFocus(boolean success, Camera camera) { // TODO Auto-generated method stub if(success) { //设置参数,并拍照 Camera.Parameters params = myCamera.getParameters(); params.setPictureFormat(PixelFormat.JPEG); params.setPreviewSize(640,480); myCamera.setParameters(params); myCamera.takePicture(null, null, jpeg); } } }
main.xml:
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" androidrientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <surfaceview android:id="@+id/surfaceView1" android:layout_width="640px" android:layout_height="480px" android:layout_gravity="center">
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wjh.camera" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="7" /> <uses-permission android:name="android.permission.CAMERA"></uses-permission> <uses-feature android:name="android.hardware.camera.autofocus" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".CameraTest_4" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
PS:其实自己去实现相机的必要性不大,大部分应用都是直接调用系统的相机,毕竟相机是涉及到一些比较专业的成像知识.
相关推荐
Android相机开发,包括调用系统相机APP拍照、拍摄视频,和自定义相机拍照、拍摄视频。
Android中的Camera相机开发设计示例演示
Android设计开发,Android手机相机的设计与实现。
xamarin android相机使用实例源码及水印菜单,具体实例代码请下载
Android自定义相机
android 自定义相机,Camera和camera2.TextureView,相机遮罩层demo
第1章 Android开发简介 1.1 Android基本概念 1.1.1 Android简介 1.1.2 Android的系统构架 1.1.3 Android应用程序框架 1.2 OMS介绍 1.2.1 OPhone介绍 1.2.2 Widget介绍 1.3 小结 第2章 Android开发环境搭建 2.1 ...
简单的Android相机程序,可实现以下功能: 1、预览 2、对焦拍照保存 3、查看图片,并且能够更新按钮的图像缩略图
Android 相机开发例程,带有详细的注释说明和工具函数
Android开发 RxPermissions使用以及自定义相机拍照demo
android 自定义 相机 连拍,效果实现,简单实用,适合初学者 android 自定义 相机 连拍,效果实现,简单实用,适合初学者
Android 调用系统相机/相册 获取照片 在照片上添加文字水印
实现功能: 自定义相机开发:支持前置,后置摄像头切换,可以自动聚焦,保存图片和显示图片
android自定义相机页面以及预览
Android调用相机并将照片显示出来,使用的是Android-17 设置权限: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_...
这里面有三种使用系统相机的方法,配合我发的博文可以更好的使用这个代码
描述见http://www.jiangwenrou.com/一个简单的android相机程序.html
本例子源码是一个基于安卓原生相机进行二次开发的相机应用源码,可以设置包括分辨率、闪光灯、构图、触屏拍照等信息,源码本身UI比较粗糙仅供开发参考,项目注释一般,编译版本2.3.3 编码GBK。
android 的自定义照相机开发,目前使用调用预览与设置偏好值,不过还没有保存图片