设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

在Fragment中使用安卓Camera SurfaceView

2014-7-7 14:47| 发布者: joejoe0332| 查看: 3356| 评论: 0|原作者: 黄瓜|来自: 伯乐在线

摘要: 由于设备厂商庞多繁杂,不同版本相机API不同,一个完整健壮的相机应用是很复杂的。如果你想实现一个完整可行的,可以考虑以CWAC Camera为基础进行开发。我的目标仅仅是演示相机开发的一些基础。 ...

这是使用Fragment在Android Studio开发相机应用系列文章5篇中的第4篇。如果你没有读过之前的文章,先从GitHub上复制一份我的工程,这篇教程主要讨论”NativeCameraFragment“。

作者语:由于设备厂商庞多繁杂,不同版本相机API不同,一个完整健壮的相机应用是很复杂的。如果你想实现一个完整可行的,可以考虑以CWAC Camera为基础进行开发。我的目标仅仅是演示相机开发的一些基础。

除了安卓的原生相机应用,你也可以在自己的项目中使用相机功能。这涉及到直接利用安卓相机接口并把结果投射到“预览”界面或者SurfaceView上。


开启相机

一旦Fragment视图对象被创建,首先做的就是把相机和相机预览界面关联起来。你可以在谷歌的开发者网站上阅读相关的文档,下面是一个参考实现:

1
2
3
4
5
6
7
8
9
10
private boolean safeCameraOpenInView(View view) {
    boolean qOpened = false;
    releaseCameraAndPreview();
    mCamera = getCameraInstance();
    qOpened = (mCamera != null);
    mPreview = new CameraPreview(getActivity().getBaseContext(), mCamera);
    FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_preview);
    preview.addView(mPreview);
    return qOpened;
}

该函数用来获取一个相机的实例对象并和我们的CameraPreview对象关联起来。

相机预览界面

例子中的CameraPreview 对象继承了SurfaceView 并实现了SurfaceHolder.callback接口,预览界面将显示相机的输入。在你看到正在拍摄的画面的同时,它将处理SurfaceHolder的生命周期:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
  * Surface on which the camera projects it's capture results.
  */
 class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
     SurfaceHolder mHolder;
     Camera mCamera;
 
     public CameraPreview(Context context, Camera camera) {
         super(context);
         mCamera = camera;
 
         // Install a SurfaceHolder.Callback so we get notified when the
         // underlying surface is created and destroyed.
         mHolder = getHolder();
         mHolder.addCallback(this);
         // deprecated setting, but required on Android versions prior to 3.0
         mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
     }
 
     public void surfaceCreated(SurfaceHolder holder) {
         // The Surface has been created, now tell the camera where to draw the preview.
         try {
             mCamera.setPreviewDisplay(holder);
             mCamera.startPreview();
         } catch (IOException e) {
             e.printStackTrace();
         }
     }
 
     public void surfaceDestroyed(SurfaceHolder holder) {
         // empty. Take care of releasing the Camera preview in your activity.
     }
 
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
         // If your preview can change or rotate, take care of those events here.
         // Make sure to stop the preview before resizing or reformatting it.
 
         if (mHolder.getSurface() == null){
             // preview surface does not exist
             return;
         }
 
         // stop preview before making changes
         try {
             mCamera.stopPreview();
         } catch (Exception e){
             // ignore: tried to stop a non-existent preview
         }
 
         // set preview size and make any resize, rotate or
         // reformatting changes here
 
         // start preview with new settings
         try {
             mCamera.setPreviewDisplay(mHolder);
             mCamera.startPreview();
 
         } catch (Exception e){
             e.printStackTrace();
         }
     }
 }

相机拍照回调

Camera.PictureCallback是安卓用来判断何时相机拍摄了照片,并且获取了输出结果的回调接口。在我的示例项目工程中实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
 
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
 
        File pictureFile = getOutputMediaFile();
        if (pictureFile == null){
            Toast.makeText(getActivity(), "Image retrieval failed.", Toast.LENGTH_SHORT)
            .show();
            return;
        }
 
        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
};

免责声明和补充

文章一发布我就从安卓相机跨设备开发专家那得到了反馈,我的目标是提供高质量的内容,所以不说清楚下面的这些问题文章就不完整 。

在我的例子中假定设备支持jpeg格式,这种假定存在风险,真实的实现需要检查是否支持jpeg格式。另一个问题 CameraHolder.PreviewCallback接口直到API版本18许多厂商才支持,这使得API 18以前PreviewCallback 将难以起作用。

此例中,我使用的默认CameraPreview 格式是NV21,已经有人推荐我使用YV12(从API 12开始支持),一定要检查下相机支持的CameraPreview格式。实现格式因设备厂商不同而不同,是不一致行为的潜在根源。

还有包括闪光灯聚焦模式在内的很多细节问题没有探讨,这些可能需要设置一些相机的参数,我已经在GitHub上更新了代码。

以上就是我直接使用安卓原生相机的例子,随便获取例子代码,同样,如果你觉得这篇文章对你有帮助欢迎分享。非常感谢。

原文链接: airpair   翻译: 伯乐在线 - 黄瓜
译文链接: http://blog.jobbole.com/72858/


酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部