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 上的相机示例的主要内容,如果未能解决你的问题,请参考以下文章

Android上的相机预览处理

Android:更改屏幕上的相机预览大小

将相机图像作为位图 Android 示例

三星 Galaxy S3 上的 Android 相机预览不正确

如何从 Android 上的相机获取位图?

如何使用相机在 Android 上的后台服务中拍照? [复制]