1.定制拍照程序的基本步骤

  1,打开照相机:Camera.open 这是独占方式打开的

  2,创建SurfaceView对象 多缓冲,多线程view

  3,添加回调事件监听器(SurfaceHolder.addCallback)

  4,预览(Camera.startPreview)

  5,拍照(Camera.takePicture),它是异步的,要在参数中指定回调函数

2.示例

2.1 主activity

  1. import android.app.Activity;
  2. import android.content.pm.PackageManager;
  3. import android.hardware.Camera;
  4. import android.os.Bundle;
  5. import android.view.Window;
  6. import android.view.WindowManager;
  7.  
  8. /*
  9. * 定制拍照程序
  10. * 注意Camera从5.0开始过期.用Camera2
  11. */
  12. public class CustomCameraActivity extends Activity {
  13.  
  14. //定制拍照 第1步,加权限
  15.  
  16. //定制拍照 第2步,准备相关api
  17. private Camera mCamera;//用来拍照
  18.  
  19. private Preview mPreview;//用来预览和处理拍照事件.它是一个自定义surfaceView
  20.  
  21. @Override
  22. protected void onCreate(Bundle savedInstanceState) {
  23. super.onCreate(savedInstanceState);
  24.  
  25. //定制拍照 第3步,设置全屏.
  26. requestWindowFeature(Window.FEATURE_NO_TITLE);
  27. getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
  28.  
  29. }
  30.  
  31. protected void onResume() {
  32. super.onResume();
  33. //定制拍照 第4步, 打开 Camera并得到Camera实例,注意这是独占的,打开后其它程序不能打开.
  34. mCamera = Camera.open();
  35. mPreview.setCamera(mCamera);
  36.  
  37. //定制拍照 第5步,构造预览view,这是一个自定义的surfaceView,拍照事件,及预览都在它内部实现.
  38. mPreview = new Preview(this);
  39. setContentView(mPreview);
  40. }
  41.  
  42. //定制拍照 第6步,释放camera
  43. @Override
  44. protected void onPause() {
  45. super.onPause();
  46.  
  47. if (mCamera != null) {
  48. mCamera.release();
  49. mCamera = null;
  50. mPreview.setCamera(null);
  51. }
  52. }
  53.  
  54. //检测Android设备是否支持照相机
  55. private boolean checkCameraHardware(){
  56. if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
  57. return true;
  58. }else{
  59. return false;
  60. }
  61. }
  62. }

2.2 用来预览和处理拍照事件的类,关键

  1. import java.io.File;
  2. import java.io.FileOutputStream;
  3. import java.util.List;
  4.  
  5. import android.content.Context;
  6. import android.hardware.Camera;
  7. import android.hardware.Camera.PictureCallback;
  8. import android.hardware.Camera.Size;
  9. import android.view.SurfaceHolder;
  10. import android.view.SurfaceView;
  11. import android.view.View;
  12. import android.view.ViewGroup;
  13. import android.view.View.OnClickListener;
  14.  
  15. /*
  16. * 它是一个自定义surfaceView,
  17. * 用来预览和处理拍照事件.
  18. * 注意它实现的接口
  19. */
  20. class Preview extends ViewGroup implements SurfaceHolder.Callback,OnClickListener {
  21.  
  22. //自定义预览和处理拍照事件 第1步, 准备相关成员
  23. SurfaceView mSurfaceView; //surface view
  24. SurfaceHolder mHolder; //SurfaceHolder
  25. Size mPreviewSize; //当前预览窗口尺寸.
  26. List<Size> mSupportedPreviewSizes; //当前设备支持的所有预览尺寸
  27. Camera mCamera; //摄像头对象
  28. Context mContext; //上下文
  29.  
  30. public Preview(Context context) {
  31. super(context);
  32. mContext = context;
  33.  
  34. //自定义预览和处理拍照事件 第2步,创建surface view
  35. mSurfaceView = new SurfaceView(context);
  36. addView(mSurfaceView);
  37. //自定义预览和处理拍照事件 第3步,得到 SurfaceHolder
  38. mHolder = mSurfaceView.getHolder();
  39.  
  40. //自定义预览和处理拍照事件 第4步,添加SurfaceHolder回调
  41. mHolder.addCallback(this);
  42. }
  43. public void setCamera(Camera camera) {
  44. mCamera = camera;
  45. if (mCamera != null) {
  46. //自定义预览和处理拍照事件 第5步,得到支持的预览尺寸,注意Camera是在本类外打开的.
  47. mSupportedPreviewSizes = mCamera.getParameters().getSupportedPictureSizes();
  48. //更新 layout
  49. requestLayout();
  50. }
  51. }
  52. //from SurfaceHolder.Callback
  53. @Override
  54. public void surfaceCreated(SurfaceHolder holder) {
  55. try {
  56. if (mCamera != null) {
  57. //自定义预览和处理拍照事件 第6步,在SurfaceView创建时,设置camera的预览view
  58. mCamera.setPreviewDisplay(holder);
  59. }
  60. } catch (Exception e) {
  61. }
  62.  
  63. }
  64. //from SurfaceHolder.Callback
  65. @Override
  66. public void surfaceDestroyed(SurfaceHolder holder) {
  67. if (mCamera != null) {
  68. //自定义预览和处理拍照事件 第7步,在SurfaceView销毁时,停止预览
  69. mCamera.stopPreview();
  70. }
  71. }
  72. //from SurfaceHolder.Callback
  73. @Override
  74. public void surfaceChanged(SurfaceHolder holder, int format, int width,
  75. int height) {
  76. //自定义预览和处理拍照事件 第8步,在SurfaceView窗口大小变化时,设置预览尺寸,大小不可随意写.
  77. //一定要注意 预览尺寸不是实际尺寸,
  78. Camera.Parameters parameters = mCamera.getParameters();
  79. parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
  80.  
  81. mCamera.setParameters(parameters);
  82. mCamera.startPreview();
  83.  
  84. }
  85. //from ViewGroup
  86. @Override
  87. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  88. //自定义预览和处理拍照事件 第9步,是本类是ViewGroup,预览view是它上面的一个view,这里设置ViewGroup的layout
  89. if (changed && getChildCount() > ) {
  90. final View child = getChildAt();
  91.  
  92. int parentWidth = r - l;
  93. int parentHeight = b - t;
  94.  
  95. int previewWidth = parentWidth;
  96. int previewHeight = parentHeight;
  97.  
  98. if (mPreviewSize != null) {
  99. previewWidth = mPreviewSize.width;
  100. previewHeight = mPreviewSize.height;
  101. }
  102. //外层的宽高比大于采集预览的宽高比.
  103. if (parentWidth * previewHeight > parentHeight * previewWidth) {
  104. final int scaledChildWidth = previewWidth * parentHeight
  105. / previewHeight;
  106. // child.layout((width - scaledChildWidth)/2,
  107. // 0,(width+scaledChildWidth)/2,height);
  108.  
  109. //child 就是surface view
  110. child.layout(, , , );
  111. } else {
  112. final int scaledChildHeight = previewHeight * parentWidth
  113. / previewWidth;
  114. //child 就是surface view
  115. child.layout(, (parentHeight - scaledChildHeight) / , parentWidth,
  116. (parentHeight + scaledChildHeight) / );
  117. }
  118.  
  119. }
  120.  
  121. }
  122. //自定义预览和处理拍照事件 第10步,从所有预览尺寸中选一个最优的.
  123. private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
  124. double ASPECT_TOLERANCE = 0.1;
  125. double targetRatio = w / h;
  126. if (sizes == null)
  127. return null;
  128.  
  129. Size optimalSize = null;
  130. double minDiff = Double.MAX_VALUE;
  131. int targetHeight = h;
  132.  
  133. for (Size size : sizes) {
  134. double ratio = size.width / size.height;
  135. if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {
  136. continue;
  137. }
  138. if (Math.abs(size.height - targetHeight) < minDiff) {
  139. optimalSize = size;
  140. minDiff = Math.abs(size.height - targetHeight);
  141. }
  142. }
  143.  
  144. if (optimalSize == null) {
  145. minDiff = Double.MAX_VALUE;
  146. for (Size size : sizes) {
  147. if (Math.abs(size.height - targetHeight) < minDiff) {
  148. optimalSize = size;
  149. minDiff = Math.abs(size.height - targetHeight);
  150. }
  151. }
  152. }
  153. return optimalSize;
  154. }
  155.  
  156. //自定义预览和处理拍照事件 第11步,在onMeasure中处理最佳预览尺寸
  157. @Override
  158. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  159. int width = resolveSize(getSuggestedMinimumWidth(),
  160. widthMeasureSpec);
  161. int height = resolveSize(getSuggestedMinimumHeight(),
  162. heightMeasureSpec);
  163.  
  164. setMeasuredDimension(width, height);
  165.  
  166. if (mSupportedPreviewSizes != null) {
  167. mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes,width, height);
  168. }
  169. }
  170. //自定义预览和处理拍照事件 第12步, 在预览view上点击屏幕时,拍照
  171. //注意回调函数
  172. public void onClick(View view) {
  173. //它是异步的.
  174. mCamera.takePicture(null, null, mPictureCallback);
  175. }
  176.  
  177. //自定义预览和处理拍照事件 第13步, 拍照的回调.
  178. private PictureCallback mPictureCallback = new PictureCallback() {
  179.  
  180. @Override
  181. public void onPictureTaken(byte[] data, Camera camera) {
  182. mCamera.startPreview();//再次启动预览,这步可选.
  183. File pictureFile = new File("/sdcard/image.jpg");
  184. try {
  185. FileOutputStream fos = new FileOutputStream(pictureFile);
  186. fos.write(data);
  187. fos.close();
  188. } catch (Exception e) {
  189. }
  190. }
  191. };
  192. }

摄像头(4)用Camera和SurfaceView自定义拍照程序的更多相关文章

  1. 摄像头标定GML Camera Calibration

    摄像头标定GML Camera Calibration GML Camera Calibration官方版是一款十分优秀出色的相机标定软件,GML Camera Calibration官方版界面友好, ...

  2. .Net 自定义应用程序配置

    .Net 自定义应用程序配置 引言 几乎所有的应用程序都离不开配置,有时候我们会将配置信息存在数据库中(例如大家可能常会见到名为Config这样的表):更多时候,我们会将配置写在Web.config或 ...

  3. VS2010制作网站自定义安装程序 转

    最近在把一个网站打包成安装程序,这方面的文章网上有很多,也看了不少,但因为开发环境的不同,遇到了一些问题,便写下这篇文章记下整个流程(有很多资源都来自互联网,由于条目颇多,所以无法说明其来处,敬请谅解 ...

  4. 自定义VS程序异常处理及调试Dump文件(一)

    自定义VS程序异常处理及调试Dump文件(一) 1. Dump文件 1. Dump文件介绍 Dump文件(Dump File),也叫转储文件,以.DMP为文件后缀.dump文件是进程在内存中的镜像文件 ...

  5. C#自定义应用程序上下文对象+IOC自己实现依赖注入

    以前的好多代码都丢失了,加上最近时间空一些,于是想起整理一下以前的个人半拉子项目,试试让它们重生.自从养成了架构师视觉 搭建框架之后,越来 越看不上以前搭的框架了.先撸个上下文对象加上实现依赖注入.由 ...

  6. 在Oracle电子商务套件版本12.2中创建自定义应用程序(文档ID 1577707.1)

    在本文档中 本笔记介绍了在Oracle电子商务套件版本12.2中创建自定义应用程序所需的基本步骤.如果您要创建新表单,报告等,则需要自定义应用程序.它们允许您将自定义编写的文件与Oracle电子商务套 ...

  7. windows系统定时重启自定义exe程序

    工作需要, Windows系统定时重启自定义exe程序. 写了如下程序, 按照说明(readme.txt)修改批处理文件中的四个参数即可: 1.readme.txt 第一个参数:进程名(不用带exe) ...

  8. 自定义wordCount程序、

    1.MyWordCount代码: package com.hadoop.mr; import java.io.IOException; import org.apache.hadoop.conf.Co ...

  9. 常用的windows小工具指令和如何打开自定义的程序

    windows可以通过 开始->运行->输入程序名 或 windows键+R键 两种方式来启动windows中自带的程序或手动安装的程序.下面介绍一些常用的windows工具的指令和如何打 ...

随机推荐

  1. js数字格式化-四舍五入精简版

    搜索网上的,数字格式化过余复杂,自己想了个简单方法,欢迎吐槽. 简化说明: '123333' => 12.3万 parseInt('123333') 字符串转整型 parseInt('12333 ...

  2. [Oracle]Oracle学习小结(1)

    1.查看Oracle数据库中的所有用户: (1)使用具有DBA权限的账户登录数据库: (2)执行select username from dba_users. SQL> conn sys 输入口 ...

  3. FireDAC如何连接ORACLE数据库

    UniDac对Oracle的Direct连接,不需要安装Oracle客户端dll,deploy时真的是方便又快捷. FireDac连接Oracle,在没有Oracle Client的情况下,是可以连接 ...

  4. C++中delete和delete[]的区别

    C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete,回收用 new[] 分配的一组对象的内存空间的时候用 delete[]. 关于 new[] 和 delete[],其中又 ...

  5. jsp日期控件My97DatePicker的使用

    My97DatePicker是一款非常灵活好用的日期控件.使用非常简单. 1.下载My97DatePicker组件包 2.将My97DatePicker包放在项目WebContent目录下 3.在页面 ...

  6. EXTJS 3.0 资料 控件之 combo 用法

    EXTJS combo 控件: 1.先定义store //年款 var comboData_ReleasYear = [ ['], ['], ['], ['] ]; 2.定义combo控件 { lay ...

  7. 微软职位内部推荐-Pricipal Dev Manager for Application Ecosystem & Service

    微软近期Open的职位: Location: China, BeijingDivision: Operations System Group Engineering Group OverviewOSG ...

  8. Java程序员的发展前景

    不知道什么时候开始,IT业初级程序员的工作性质与进城打工的"农民工"变得如此惊人的相似.很多IT公司的高管认为"人便宜,就是要用到坏掉,然后再找更便宜.更年轻的" ...

  9. 3111: [Zjoi2013]蚂蚁寻路 - BZOJ

    题目描述 Description在一个 n*m 的棋盘上,每个格子有一个权值,初始时,在某个格子的顶点处一只面朝北的蚂蚁,我们只知道它的行走路线是如何转弯,却不知道每次转弯前走了多长.蚂蚁转弯是有一定 ...

  10. Extjs4.2——bbar的默认类型(xtype)

    bbar:在Panel经常使用的工具栏 如下面的示例——这将牵涉本文要追寻的问题:在下面的Panel中的bbar第一个组件明确指定的xtype:'button',第二个没有明确指出,那么它是何类型,为 ...