Android 上的相机示例
Posted
技术标签:
【中文标题】Android 上的相机示例【英文标题】:Camera on Android Example 【发布时间】:2012-01-16 23:26:59 【问题描述】:我想写一个活动:
-
显示相机预览(取景器),并有一个“捕捉”按钮。
按下“捕获”按钮时,拍摄一张照片并将其返回给调用活动(setResult() 和 finish())。
是否有适用于每台设备的完整示例?一个可以拍照的简单开源应用程序的链接将是理想的答案。
我目前的研究:
这是一个常见的场景,有很多关于这个的问题和教程。
主要有两种方法:
-
使用 android.provider.MediaStore.ACTION_IMAGE_CAPTURE 事件。见this question
直接使用相机 API。请参阅this example 或this question (with lots of references)。
方法 1 本来是完美的,但问题是每个设备上的意图实现方式不同。 在某些设备上运行良好。但是,在某些设备上,您可以拍照,但它永远不会返回到您的应用程序中。在某些设备上,当您启动 Intent 时没有任何反应。 通常它还会将图片保存到 SD 卡,并且需要 SD 卡存在。每个设备上的用户交互也不同。
方法 2 的问题是稳定性。我尝试了一些示例,但我设法阻止相机在某些设备上工作(直到重新启动)并完全冻结另一台设备。在另一台设备上捕获成功,但预览仍然是黑色的。
我会使用 ZXing 作为示例应用程序(我经常使用它),但它只使用预览(取景器),不拍照。我还发现在某些设备上,ZXing 在光照条件发生变化时并没有自动调整白平衡,而原生相机应用却可以正常进行(不确定是否可以修复)。
更新:
有一段时间我直接使用相机 API。这提供了更多控制(自定义 UI 等),但我不会向任何人推荐它。我会在 90% 的设备上工作,但时不时会发布新设备,但会遇到不同的问题。
我遇到的一些问题:
处理自动对焦 处理闪光灯 支持带有前置摄像头、后置摄像头或两者兼有的设备 每台设备都有不同的屏幕分辨率、预览分辨率(并不总是与屏幕分辨率匹配)和图片分辨率的组合。所以总的来说,我不建议走这条路,除非没有其他办法。两年后,我放弃了自定义代码并切换回基于 Intent 的方法。从那以后,我遇到的麻烦少了很多。我过去在基于 Intent 的方法中遇到的问题可能只是我自己的无能。
如果你真的需要走这条路,我听说如果你只支持 Android 4.0+ 的设备会容易得多。
【问题讨论】:
【参考方案1】:方法 2 的问题是稳定性。我尝试了一些示例,但我设法阻止相机在某些设备上工作(直到重新启动)并完全冻结另一台设备。在另一台设备上捕获成功,但预览仍然是黑色的。
示例中存在错误或设备存在兼容性问题。
【讨论】:
我试过你的例子,我注意到一件事:当我打开预览,然后让我的设备进入睡眠状态(三星 Galaxy SII 右侧的按钮)并再次唤醒它时,预览画面全黑,拍照失败。我想它一定与 onPause/onResume 实现有关? @Zainodis:确保您使用的是最新版本的示例——我在大约一个月前根据有关此问题的一些反馈对其进行了更新。 啊,谢谢,我 2 天前刚刚实现了它,但我会重新检查 :) 在更新到最新版本的代码后,如果我仍然遇到这个问题,我会告诉你。跨度> 好的,我现在确定我的代码与这个匹配:github.com/commonsguy/cw-advandroid/blob/master/Camera/Picture/… 但是手头的问题仍然存在 - 知道如何解决这个问题吗?我正在使用 Android 版本 2.3.4 的三星 Galaxy SII 上运行您的示例。另外需要注意的是:我正在使用 startActvityForResult 开始您的相机示例 - 尽管我不确定这是否与我遇到的睡眠问题有关。 @Zainodis:好的,我会看看我能不能拿到其中一个。同时,我有opened an issue on this——请使用该问题获取您发现的更多信息。谢谢!【参考方案2】:CommonsWare 提供的示例运行良好。该示例在按原样使用时有效,但以下是我在为我的用例修改它时遇到的问题:
-
在第一张照片完成之前切勿拍摄第二张照片,换句话说,
PictureCallback.onPictureTaken()
已被调用。 CommonsWare 示例为此使用了inPreview
标志。
确保您的SurfaceView
是全屏的。如果您想要更小的预览,您可能需要更改预览大小选择逻辑,否则预览可能不适合某些设备上的SurfaceView
。某些设备仅支持全屏预览大小,因此保持全屏是最简单的解决方案。
要向预览屏幕添加更多组件,根据我的经验,FrameLayout
效果很好。我首先使用LinearLayout
在预览上方添加文本,但这违反了规则#2。当使用FrameLayout
在预览之上添加组件时,预览分辨率没有任何问题。
我还在GitHub 上发布了一个与Camera.open()
相关的小问题。
【讨论】:
您的第 2 点不正确。我正在使用SurfaceView
本身提供的尺寸,它应该适用于任何尺寸SurfaceView
。没有假设它是全屏的——事实上,在 Android 3.0+ 上,它不是全屏的,因为有一个操作栏。
我遇到的问题是,在一台设备上,唯一的预览尺寸是 320x240(全屏分辨率)。如果SurfaceView
小于此值,则示例将不会显示任何预览。
出于好奇,哪个设备?毫无疑问,我的代码假定至少有一个小于SurfaceView
大小的有效预览分辨率。
这是三星 Galaxy Y Pro B5510(不错的入门级手机)。在我测试过的所有其他手机上,这都不是问题。我编辑了答案以改进第 2 点的措辞。【参考方案3】:
"the recommended way to access the camera is to open Camera on a separate thread"。否则,Camera.open() 可能需要一段时间,并且可能会阻塞 UI 线程。
"Callbacks will be invoked on the event thread open(int) was called from"。这就是为什么要通过摄像头预览回调实现最佳性能(例如,将它们编码为低延迟视频以进行实时通信),我建议在新的 HandlerThread 中打开摄像头,如 here 所示。
【讨论】:
以上是关于Android 上的相机示例的主要内容,如果未能解决你的问题,请参考以下文章