【问题标题】:Android - Camera App passed null surfaceAndroid - 相机应用程序通过空表面
【发布时间】:2015-06-03 09:30:15
【问题描述】:

我已经尝试了 stackoverflow 上给出的所有可能的解决方案,但仍然没有达到我想要的。我想使用带有服务的 Camera API 拍照。用户点亮屏幕时应拍摄照片,但屏幕仍处于锁定状态。我看到了关于虚拟表面等的不同帖子......但它们都没有工作,当然我一定在我的代码中犯了错误,因为我是相机 API 的新手。我的应用程序是这样进行的:我安排了一个 AlarmManager 来启动服务:

public int onStartCommand(Intent intent,int flags,int startId) {
        Log.i("service","start");
        Calendar finServ=Calendar.getInstance();
        String all=intent.getStringExtra("all");
        nomevt=all.split(Pattern.quote("**"))[3];
        Scanner sc;
        String str="";
        try {
            sc = new Scanner(new File(getFilesDir(),"Event.evt"));
            while(sc.hasNext()) {
                str=sc.next();
                if(all.equals(str)) break;
            }
            sc.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if(!all.equals(str)) stopSelf();
        else {
            finServ.setTimeInMillis(toMillis(str.split(Pattern.quote("**"))[1]));
            Calendar now=Calendar.getInstance();
            now.setTime(new Date());
            while(finServ.after(now)) {
                PowerManager pm=(PowerManager)getSystemService(Context.POWER_SERVICE);
                if(pm.isScreenOn()) {
                    //AsyncCapture ac=new AsyncCapture(this);
                    //ac.execute("nomevt");
                    photo();
                    Log.i("screen","on");
                    while(pm.isScreenOn()) {
                        pm=(PowerManager)getSystemService(Context.POWER_SERVICE);
                    }
                }
                now.setTime(new Date());
            }
            stopSelf();
        }
        return super.onStartCommand(intent, flags, startId);
    }`
<br>The service will call `photo()` when the screen is light on. <br> 
`public void photo() {
        cam=Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
        try {
            cam.unlock();
            /*WindowManager wm=(WindowManager)this.getSystemService(Context.WINDOW_SERVICE);
            WindowManager.LayoutParams params=new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                    PixelFormat.TRANSLUCENT);*/
            SurfaceView sv=new SurfaceView(this);
            //wm.addView(sv, params);
            ViewGroup.LayoutParams param=new ViewGroup.LayoutParams(1,1);
            sv.setLayoutParams(param);
            sv.setZOrderOnTop(true);
            SurfaceHolder mHolder=sv.getHolder();
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            Log.i("holder",(mHolder==null)+"");
            cam.setPreviewDisplay(mHolder);
            cam.startPreview();
            cam.takePicture(null,null,this);
            //wm.removeView(sv);
            Log.i("take","picture");
        } catch (IOException e) {
            Log.e("error",e.getMessage());
            e.printStackTrace();
        }catch(RuntimeException re) {
            Log.e("error",re.getMessage()+"");
            re.printStackTrace();
        }finally{
            cam.stopPreview();
            cam.release();
        }
    }

takePicture() 中,我只是保存图像,此方法在我在活动中测试时有效。 日志显示错误Camera : app passed NULL surfaceerror : setPreviewTextureFailed。我放了一个日志来查看mHolder 是否为空,但不是。
为什么setPreviewDisplay()会报错?

【问题讨论】:

    标签: android service camera surfaceview


    【解决方案1】:

    您应该使用SurfaceTexturesetPreviewTexture() 而不是SurfaceHolder

    SurfaceTexture surfaceTexture = new SurfaceTexture(0);
    cam.setPreviewTexture(surfaceTexture);
    

    setPreviewDisplay() 中已抛出错误Camera : app passed NULL surface 是因为没有创建表面。

    如果你仍然想使用SurfaceHolder,你应该先实现SurfaceHolder.Callback,然后在surfaceCreated()方法中实现setPreviewDisplay(),以确保在setPreviewDisplay()之前创建了一个表面。

    请注意,在将表面添加到视图层次结构之前,不会创建表面。

    编辑

    回到你setPreviewTexture()时的错误,因为你使用了cam.unlock();,你的相机暂时释放给另一个进程使用(阅读更多关于unlock()方法here) .这就是为什么当您调用 setPreviewTexture() 时出现错误 java.io.IOException: setPreviewTexture failed

    解决方案是删除代码中的cam.unlock(); 行。

    【讨论】:

    • 谢谢,但我已经尝试过多次它会引发错误setPreviewTexture failed “将表面添加到视图层次结构”是指将其添加到我的 .xml 应用程序文件中?但是,由于应用程序没有启动,我怎么能从服务中访问它呢?
    • @Biratus 不,您可以在运行时使用addView() 添加它(您已经尝试过)。如我所见,您正在尝试从相机“无预览”捕获图像,对吗?在那种情况下,我认为使用纹理对我们来说是最好的方法。你能告诉我你在使用SurfaceTexture时得到了什么吗?它非常适合我。
    • 是的,这就是我想要的,或者使用虚拟预览...我已经测试过 SurfaceTexture !我写了 cam.setPreviewTexture(new SurfaceTexture(0)); 然后 startPreview,takePicture... 当调用 setPreviewTexture 时,它显然会抛出 Java.io.IOException: setPreviewTexture failed。而且我无法向视图添加表面纹理,因为它不是视图。
    • @Biratus 查看我的更新答案。我想你的问题会解决的。您不需要视图即可使用相机。这就是我选择SurfaceTexture的原因。
    • @Biratus 你能告诉我你的问题是否解决了。如果没有,您遇到了什么样的错误?
    猜你喜欢
    • 2015-07-31
    • 2012-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多