安卓相机表面视图

12

我正在尝试创建一个表面视图,让摄像头在视野范围内时渲染在表面上。目前我在相机视图上只能看到黑屏。我已经在谷歌和这里搜索了一番,但是迄今为止还没有找到我要的内容。有人可以给我一些建议吗。

2个回答

20

我编写了一个可以帮助你的类。

    public class Preview_can_work extends Activity {
        private SurfaceView surface_view;  
        private Camera mCamera;
        SurfaceHolder.Callback sh_ob = null;
        SurfaceHolder surface_holder        = null;
        SurfaceHolder.Callback sh_callback  = null;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            getWindow().setFormat(PixelFormat.TRANSLUCENT);

            surface_view = new SurfaceView(getApplicationContext());
            addContentView(surface_view, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

            if (surface_holder == null) {
                surface_holder = surface_view.getHolder();
            }

            sh_callback = my_callback();
            surface_holder.addCallback(sh_callback);
        }

            SurfaceHolder.Callback my_callback() {      
                SurfaceHolder.Callback ob1 = new SurfaceHolder.Callback() {

                    @Override
                    public void surfaceDestroyed(SurfaceHolder holder) {
                          mCamera.stopPreview();
                          mCamera.release();
                          mCamera = null;
                    }

                    @Override
                    public void surfaceCreated(SurfaceHolder holder) {
                        mCamera = Camera.open();

                          try {
                               mCamera.setPreviewDisplay(holder);  
                          } catch (IOException exception) {  
                                mCamera.release();  
                                mCamera = null;  
                          }
                    }

                    @Override
                    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                            int height) {
                        mCamera.startPreview();
                    }
                };
                return ob1;
        }
    }

在您的清单文件中复制以下代码以获取相机权限

<uses-permission android:name="android.permission.CAMERA"/>

说明:

SurfaceView是一种包含SurfaceHolder的View类型。 SurfaceHolder保存我们可以显示媒体(通常是帧)的表面。

mCamera是一个Camera对象,它将包含相机实例。

当您想要持有默认的相机实例时,可以简单地调用Camera.open();

Camera mCamera = Camera.open();
现在您已经打开了相机或者正在使用默认相机实例。现在需要从相机中捕获帧并在表面上显示它,但是没有任何表面,您无法显示它。
这里,surfaceView提供surfaceHolder,而surfaceHolder又提供surface来显示相机帧。当surface被创建时,将调用三个回调函数。
1. public void surfaceCreated(SurfaceHolder holder)
2. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
3. public void surfaceDestroyed(SurfaceHolder holder)

Note:- 当您的应用程序暂停时,表面将被销毁。

surfaceCreated: surfaceCreated是一个回调函数,当您的表面被创建时将调用它。在此函数中,您可以打开相机并设置其他属性。

surfaceChanged: 这将在您的表面被创建时至少调用一次。之后,每当您的表面变化(设备旋转)时都会调用它。在这里,您可以开始预览,因为您的表面已经被创建。

surfaceDestroyed: 每当您的表面被销毁时都会调用此函数。现在如果您没有表面,那么您在哪里可以显示相机帧,所以我使用mCamera.release()释放了相机。

这非常重要,因为如果您的活动处于暂停状态,并且任何其他活动尝试打开相机,则无法打开它,因为您已经打开了相机。相机是共享资源,因此一次只能由一个应用程序使用。因此,请记住一件事:每当您打开相机时,请始终释放它。

stopPreview: 当您开始预览时,相机开始捕获帧并在表面上显示。现在,如果您的表面已被销毁,则需要停止从相机捕获帧,因此您必须调用mCamera.stopPreview


感谢Bharat,我肯定会尝试一下!再次感谢。有人知道一篇关于“模拟器运行时相机无法工作”的好文章吗? 这仍然是真的吗? - Kitaro
1
@Override public void surfaceDestroyed(SurfaceHolder holder) { mCamera.stopPreview(); mCamera.release(); mCamera = null; }您能告诉我上述方法的作用吗?我们需要使用release()函数吗?因为我不确定release()函数是用来做什么的。 - Kitaro
@BharatSharma:感谢您的代码,它可以工作,但相机视图显示旋转的图像(上下)...请帮助我。 - Erma Isabel
要设置相机视图,您需要根据您的API级别调用setRequestedOrientation()或setRotation。这些函数针对相机视图旋转采用不同的参数。您可以根据您的需求使用它们。 - Bharat Sharma
根据我的经验,您可以创建一个新的Surface Holder并将其添加到您的Frame Layout中。问题是您不能同时在两个不同的位置使用相机,所以您可以创建另一个Surface Holder回调并将其添加到您的Surface Holder中。我没有尝试过,但您可以尝试一下。如果不起作用,那么只需将前一个Surface的帧复制到另一个Surface即可。 - Bharat Sharma
显示剩余3条评论

0

请确保您已添加以下权限:

<uses-permission android:name="android.permission.CAMERA"/>

还需要添加以下窗口属性:

getWindow().setFormat(PixelFormat.TRANSLUCENT);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
                 WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

如果那个不起作用,请发布一些代码以便我们帮助您


谢谢,我已经按照你的建议添加了权限;我在考虑使用 surfaceChanged 函数,目前我在相机预览界面上只能看到黑色……我不明白为什么。 - Kitaro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接