修正Android摄像头API

这几天本人参加了一个公司举办的编程马拉松,我打算使用Android摄像头来做。我一直都认为Android的API很糟糕,但是没有详细说出哪些地方糟糕,也没有说怎么改进会更好。趁这个机会,现在我就来解释解释。

我认为,Android关于摄像头的API非常糟糕,如果你没有用过,那么自己花点时间看看去吧。使用这个Camera API的 时候,经常会使开发者使用错误,会导致开发者忽略很多重要的东西,然后出问题了也很难发现,甚至在StackOverFlow上也很不乐观。换句话说,如 果有API需要你读完十个步骤(还有几个标记为“重要”的),那么,其实它是有问题的,怎么会写出这么麻烦的API呢?我们要改进它。

所以我打算重新构造它。我把重构后的代码放在GitHub上( EasyCamera),以下列出了我改的地方,还有修改的理由:

  1. 在使用startPreview()方法之前,需要先调用setPreviewDisplay(..)方法,然后再进行拍照的时候又需要调用它。为 什么不改进一下呢?如果不执行这个方法的话就会出问题,我们可以简单地抛出一个异常“Preview display not set”,但是这样终究不太好。所以,这个setPreviewDisplay(..)可以不要了,我们直接让startPreview(..)带上 surface作参数,然后还可以重载它让SurfaceTexture也作为参数传递进去。
  2. 在改进了预览设置后,现在开始改进预览操作。如果在拍照的时候,没有调用startPreview这个方法,那也会出问题,这里也可以简单抛出一个 异常“Preview not started”,但是要知道,这个异常是在运行时抛出的。所以,takePicture(..)这个方法也要改进,把它移到Camera这个类外面,放 到CameraAction类里。其它的需要在preview调用后才能使用的方法也需要这样改进(我暂时不知道有哪一些,当前的API里也没有列出 来)。接下来就是怎么获取一个CameraAction类实例了,很简单,直接调用startPreview(..)就可以返回一个 CameraAction了。
  3. 目前我们的改进只是让使用方法更加直观,然后减少出错的情况。不过takePicture这个方法好像有点奇怪,可以给它的参数全部传null值, 但是里面还有两个重写的方法需要这些参数。理论上说,传null值也可以,但是还有别的法子解决这个问题。其一就是介绍一个接口叫 PictureCallback,它有四个可以调用的方法,然后还提供一个默认的实现类,叫BasePictureCallback。当然,你会发现,在 这个场景中,好像也不太合适,因为这个例子中你传递这个callback接口的话,什么事都不会发生,但是传递null值的话,就不一样了(会出问题), 但是在我的手机上测试的时候,我传递一个shutter callback时,快门声音就会响,而传递null值就不会响。所以,这里主要介绍的就是使用这个callback接口,带有一个实现类,包含所有你需 要的所有方法。
  4. 到目前为止,改的还不错,还有就是,在照相完成后,需要restart preview,但是默认让它自动 restart也不是很好。目前的情况是,我们只有一个CameraAction类,然后调用startPreview(..)方法需要传递一个 surface参数,是不是需要引进一个restartPreview()方法呢?当然不用,这里我们让这个接口类的方法都返回一个布尔值,如果需要 restart preview,就可以返回true,这样会比较好,然后又有一个问题,如果这个callback类没有这4个方法调用呢,依赖这4个方法来得出是否需要 restart preview终究不好,所以,还需要在callback实现类中加一个restartPreview属性,只有在最后一个方法被调用时这个属性才会被设 置成true。
  5. 主要的步骤已经改进好了,还有其它的一些小问题需要改进,比如,关闭和打开camera的方法是不对称的,“open”和“release”配对感 觉不好,应该是“open”和“close”或者“acquire”和“release”。所以我觉得用“close”更好一些,况且(如果使用 java7),可以好好利用AutoClosable接口,还有try-with-resource结构(详情请查看java7新特性)。
  6. 在调用getParameter()方法的时候可以得到一份参数的副本,然后,你可能需要把更改过的这个副本设置回去,也是挺合理的。如果能提供一 个camera.setParameter(..)方法,可能使用起来会方便一些,不过Parameter类已经提供了很多方法了,所以在Camera类 里面添加不太好。或许这里可以设置可变参数?(当然现在也还没实现)
  7. 这个Camera的API糟糕的原因之一还有它的错误反馈,基本上可能得到一个报错信息“Came.takePicture failed”,无论什么原因导致的,通过以上的这些步骤,在某些情况下会过滤掉一些我们需要的异常信息,不过最好还是应该得到精确的报错信息。
  8. 我们的目的就是要让Camera使用更加友好(现在还不是),所以EasyCamera是一个容易使用的接口,CameraActions也是一个可造性很好的类。

本人的这个EasyCamera工程目前只是一个初版,也还没有用于实际生产环境中,但是我也希望得到大家的宝贵意见,争取把它做得更好,不断改进它。有的情况下,它也可以包含其它一些摄像头的功能,比如前后摄像头切换等等。

蹩脚的API会让开发者浪费大量的时间,金钱和精力,所以在设计API的时候,需要某些特殊的技能,还要多进行思考。Josh Bloch的关于API设计的见解很中肯,我强烈推荐它。事实上我也违反了其中一条-“if in doubt, leave it out”-通过CameraAction这个类我们可以完全掌控Camera,所以也有可能有很多操作是没用的,因为我对所有Camera的属性也不是很 了解,所以在代码里我也不会限制用户去做一些其它的操作。

一开始我写这篇文章的时候,其实我也没打算写EasyCamera这个东西,而事实上我是花了两个小时把它写出来了。最后,我建议所有开发者们,在 你遇到一些蹩脚的API时,可以像以上操作一样,自己动手做一些改造,多思考怎么设计和实现它们,然后你会发现这样比你慢慢修改和封住更省事,然后用起来 也就得心应手了。

修正Android摄像头API

时间: 2024-10-24 16:24:45

修正Android摄像头API的相关文章

android摄像头的autoFocus-----循环自动聚焦的实现

参考:http://blog.sina.com.cn/s/blog_7dbac1250101mloj.html 采用重力感应方式已实现 要实现android摄像头的autoFocus,并不难,但要实现自动连续的自动聚焦就要费点劲.这里将我的研究思路和解决方法记录于此.实现自动聚焦,方法有如下: 第一:最常见的实现---利用按键或拍照前一次性自动聚焦 在Activity里申明变量private AutoFocusCallback myAutoFocusCallback = null;然后 //自动

Android开发-API指南-<uses-feature>

<uses-feature> 英文原文:http://developer.android.com/guide/topics/manifest/uses-feature-element.html 采集(更新)日期:2014-7-7 搬迁自原博客:http://blog.sina.com.cn/s/blog_48d491300100zmwf.html 在本文中 Google Play 和基于设备特性的过滤机制 基于显式声明的特性需求进行过滤 基于隐含的特性需求进行过滤 对蓝牙特性的特殊处理 对应用

Android开发-API指南-应用程序开发基础

Application Fundamentals 英文原文:http://developer.android.com/guide/components/fundamentals.html 采集日期:2014-04-16 搬迁自原博客:http://blog.sina.com.cn/s/blog_48d491300101h41p.html 在本文中 应用程序组件 激活组件 Manifest 文件 声明组件 声明应用程序的需求 应用程序资源 Android 应用程序是用 Java 语言编写的.And

使用Android中API建议的方式实现SQLite数据库的增、删、改、查的操作

package com.examp.use_SQLite.dao; import java.util.ArrayList; import java.util.List; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import com.examp

安卓一键ROOT, android root api sdk 服务支持

android 一键root sdk已经开发完毕,支持PC 及手机端: 鉴于现在手机端的需求比较大,特提供SDK外放服务:以及ROOT技术支持: 商务合作  ROOT后您可以: 1.删除系统应用,定制个性化系统 2.各种暗扣(当然现在国内环境不行,但是您有渠道还是可以的) 3.静默安装各种推广APP 4.打压竞争对手APP 5.后台静默刷流量 6.完全控制他人手机 7.等等等 安卓一键root sdk 服务,安卓root技术支持, android root sdk, android root a

Android 中文API (65) —— BluetoothClass[蓝牙]

前言 本章内容是android.bluetooth.BluetoothClass,为Android蓝牙部分的章节翻译.用于描述远端设备的类型,特点等信息,通过getBluetoothClass()方法获取代表远端设备属性的BluetoothClass对象.版本为Android 2.3   r1,翻译来自中山大学的"Android Club SYSU",欢迎访问他们的WIKI:http://www.android-wiki.net,再次感谢"Android Club SYSU&

Android 中文API (67) —— BluetoothClass.Device.Major

前言 本章内容是android.bluetooth.BluetoothClass.Device.Major,为Android蓝牙部分的章节翻译,版本为Android 2.3   r1,翻译来自中山大学的"Android Club SYSU",欢迎访问他们的WIKI:http://www.android-wiki.net,再次感谢"Android Club SYSU"!期待你一起参与Android中文API的翻译,联系我 [email protected]. 声明 欢

Android 中文API (68) —— BluetoothClass.Service

前言 本章内容是 android.bluetooth.BluetoothClass.Service,为Android蓝牙部分的章节翻译,版本为 Android 2.3   r1,翻译来自中山大学的"Android Club SYSU",欢迎访问他们的WIKI:http://www.android-wiki.net,再次感谢"Android Club SYSU"!期待你一起参与Android中文API的翻译,联系我 [email protected]. 声明 欢迎转载

android sdk api结构解析

一.系统级:android.accounts android.app     1.OS 相关         android.os         android.os.storage         android.hardware(传感器)         android.security         android.drm(这个应该是为所有app服务的)     2.VM 相关         dalvik.system         dalvik.bytecode 二.程序框架