19

我想写一个活动:

  1. 显示相机预览(取景器),并有一个“捕捉”按钮。
  2. 当按下“捕获”按钮时,拍摄一张照片并将其返回给调用活动(setResult() & finish())。

是否有适用于每台设备的完整示例?一个可以拍照的简单开源应用程序的链接将是理想的答案。


到目前为止我的研究:

这是一个常见的场景,并且有很多关于此的问题和教程。

主要有两种方法:

  1. 使用 android.provider.MediaStore.ACTION_IMAGE_CAPTURE 事件。看到这个问题
  2. 直接使用相机 API。请参阅此示例此问题(有很多参考资料)

方法 1 本来是完美的,但问题是每个设备上的意图是不同的。在某些设备上它运行良好。但是,在某些设备上,您可以拍照,但它永远不会返回到您的应用程序。在某些设备上,当您启动意图时没有任何反应。通常它还会将图片保存到 SD 卡中,并且需要 SD 卡存在。每个设备上的用户交互也不同。

方法2的问题是稳定性。我尝试了一些示例,但我设法阻止相机在某些设备上工作(直到重新启动)并完全冻结另一台设备。在另一台设备上捕获工作,但预览保持黑色。

我会使用 ZXing 作为示例应用程序(我经常使用它),但它只使用预览(取景器),不拍照。我还发现在某些设备上,ZXing 没有在光照条件发生变化时自动调整白平衡,而原生相机应用程序却可以正常进行(不确定是否可以修复)。


更新:

有一段时间我直接使用相机 API。这提供了更多控制(自定义 UI 等),但我不会向任何人推荐它。我会在 90% 的设备上工作,但时不时会发布新设备,但会遇到不同的问题。

我遇到的一些问题:

  • 处理自动对焦
  • 处理闪光灯
  • 支持带有前置摄像头、后置摄像头或两者的设备
  • 每个设备都有不同的屏幕分辨率、预览分辨率(并不总是与屏幕分辨率匹配)和图片分辨率的组合。

所以总的来说,我不建议走这条路,除非没有其他办法。两年后,我放弃了自定义代码并切换回基于 Intent 的方法。从那以后,我遇到的麻烦少了很多。我过去在基于 Intent 的方法中遇到的问题可能只是我自己的无能。

如果你真的需要走这条路,我听说如果你只支持 Android 4.0+ 的设备会容易得多。

4

3 回答 3

9

方法2的问题是稳定性。我尝试了一些示例,但我设法阻止相机在某些设备上工作(直到重新启动)并完全冻结另一台设备。在另一台设备上捕获工作,但预览保持黑色。

示例中存在错误或设备存在兼容性问题。

于 2011-12-09T20:27:11.633 回答
1

CommonsWare 给出的例子运行良好。该示例在按原样使用时有效,但以下是我在为我的用例修改它时遇到的问题:

  1. 切勿在第一张照片完成之前拍摄第二张照片,换句话说PictureCallback.onPictureTaken(),已被调用。CommonsWare 示例inPreview为此目的使用该标志。
  2. 确保你SurfaceView是全屏的。如果您想要更小的预览,您可能需要更改预览大小选择逻辑,否则预览可能不适合SurfaceView某些设备。某些设备仅支持全屏预览大小,因此保持全屏是最简单的解决方案。

向预览屏幕添加更多组件,FrameLayout在我的经验中效果很好。我首先使用 aLinearLayout在预览上方添加文本,但这违反了规则 2。使用 aFrameLayout在预览之上添加组件时,预览分辨率没有任何问题。

我还在GitHub 上Camera.open()发布了一个小问题。

于 2011-12-10T12:29:13.310 回答
0

“访问相机的推荐方法是在单独的线程上打开相机”。否则,Camera.open()可能需要一段时间,并且可能会阻塞 UI 线程。

“回调将在事件线程 open(int) 被调用时被调用”。这就是为什么要通过摄像头预览回调实现最佳性能(例如,将它们编码为低延迟视频以进行实时通信),我建议在新的 HandlerThread 中打开摄像头,如下所示

于 2014-02-25T17:50:47.187 回答