欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android Camera快要被气到吐血身亡了!!!

程序员文章站 2022-05-08 22:36:33
...

使用Camera是一件多么平常无奇的事,但是就是这个平常无奇,今天出现了离奇的鬼异现象,几乎快要把我气到吐血身亡了!!!做为一个拥有n多年工作经验的Android开发工程师,遇到问题是不会折服的,但是折腾了大半天,不得不为这个见鬼的Bug气个半死。下面记录一下这个鬼异的Bug,看看大家有没有遇到过,或者有没有人解释一下这是为什么?具体原因?

今天,我想写个Camera的使用Demo,结果画面出来一秒后就不动了,也没多少代码,找到以前的项目对比,没错啊,就是这么用的呀,为什么不行呢?运行以前的代码,OK呀,说明是代码的问题,手机是没问题的,我这里运行了两部手机,问题是一样的,一部是Android 7.1.1版本,一部是Android6.0版本。Camera的使用可以说是再简单不过的了,刚开始我是不服啊,所以慢慢看啊,找啊,就是看不出来,后来通过排队法找到了这个鬼异的Bug,但是为什么会这样,具体原理我还是没明白。

开发工具:Android Studio 3.4.1,build.gradle配置:最小版本21,目标版本与编译版本都是27,Camera权限也添加了

简化过的代码如下(超级少的代码):

public class MainActivity extends AppCompatActivity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SurfaceView surfaceView = new SurfaceView(this);
        setContentView(surfaceView);
        final SurfaceHolder surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {
            public void surfaceCreated(SurfaceHolder holder) {
                Camera camera = Camera.open(0);
                try {camera.setPreviewDisplay(surfaceHolder);} catch (IOException e) { }
                camera.startPreview();
            }
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
            public void surfaceDestroyed(SurfaceHolder holder) { }
        });
    }
}

先不要说我代码风格这样写太差,我只是简化成这样代码最少最紧凑,这是完整代码,运行是OK的,完全没有问题,这是我知道Bug之后才写出来这个可以运行的代码,接下来演示一下Bug的出现,我们在Camera camera = Camera.open(0)这行代码下面添加一个预览回调,如下:

public class MainActivity extends AppCompatActivity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SurfaceView surfaceView = new SurfaceView(this);
        setContentView(surfaceView);
        final SurfaceHolder surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {
            public void surfaceCreated(SurfaceHolder holder) {
                Camera camera = Camera.open(0);
                camera.setPreviewCallback(new Camera.PreviewCallback() {
                    @Override
                    public void onPreviewFrame(byte[] data, Camera camera) { }
                }); 
                try {camera.setPreviewDisplay(surfaceHolder);} catch (IOException e) { }
                camera.startPreview();
            }
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
            public void surfaceDestroyed(SurfaceHolder holder) { }
        });
    }
}

这时你再运行就可以看到那鬼异的Bug出现了,视频画面出来1秒钟后就不动了,如果你一开始就是这么写的,你怎么会想到把添加回调的代码注释了就能解决问题,而且添加回调我们是必须要使用的,也不可能删除的呀,怎么看代码都没问题,所以,气人不气人!!!即想要设置回调,又想能正常运行咋办??把Camera设置成成员变量,其他什么都不变,如下:

public class MainActivity extends AppCompatActivity {
    Camera camera;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SurfaceView surfaceView = new SurfaceView(this);
        setContentView(surfaceView);
        final SurfaceHolder surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {
            public void surfaceCreated(SurfaceHolder holder) {
                camera = Camera.open(0);
                camera.setPreviewCallback(new Camera.PreviewCallback() {
                    @Override
                    public void onPreviewFrame(byte[] data, Camera camera) { }
                });
                try {camera.setPreviewDisplay(surfaceHolder);} catch (IOException e) { }
                camera.startPreview();
            }
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
            public void surfaceDestroyed(SurfaceHolder holder) { }
        });
    }
}

运行,OK,通过!气人不气人??太气了!!!谁能想到把Camera声明成了局部变量会出现这样的Bug,这里声明成员变量和局部变量有舍区别了??没区别的好吧!!但是声明为成员变量问题就是没了,鬼异不异吧!哪位大神能告诉我这是怎么回事??