Android - cam.setPreviewDisplay(holder) 遇到 IOError [英] Android - cam.setPreviewDisplay(holder) running into IOError

查看:32
本文介绍了Android - cam.setPreviewDisplay(holder) 遇到 IOError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将相机的图像用作动态壁纸的一部分.

I am trying to use the camera's image as part of live wallpaper.

在我声明的引擎中,我有以下代码:

In the Engine that I declared, I have this code:

public class Class extends WallpaperService
{
    Camera cam;

    @Override
    public void onCreate()
    {
        super.onCreate();
        cam = Camera.open();
    }

    //...

    @Override
    public Engine onCreateEngine()
    {
        return new CubeEngine(cam);
    }

    class CubeEngine extends Engine
    {
        Camera cam;

        CubeEngine(Camera cam)
        {
            this.cam=cam;
        }

        //...

        @Override
        public void onDestroy()
        {
            if (cam != null)
            {
                cam.stopPreview();
                cam.setPreviewCallback(null);
                cam.release();
                cam = null;
            }
            super.onDestroy();
        }

        @Override
        public void onSurfaceChanged(SurfaceHolder holder, int format,
                int width, int height)
        {
            try
            {
                cam.setPreviewDisplay(holder);
                cam.startPreview();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            super.onSurfaceChanged(holder, format, width, height);
        }

        @Override
        public void onSurfaceCreated(SurfaceHolder holder)
        {
            super.onSurfaceCreated(holder);
        }

        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder)
        {
            if (cam != null)
            {
                cam.stopPreview();
                cam.setPreviewCallback(null);
                cam.release();
                cam = null;
            }
            super.onSurfaceDestroyed(holder);
        }

        //...
    }
}

cam 是一个被声明为 Camera.open();

cam is a Camera that was declared as Camera.open();

当我运行它时,我得到:java.io.IOException: setPreviewDisplay failed

When I run this I get: java.io.IOException: setPreviewDisplay failed

我现在遇到了这个异常:

I am now getting this exception:

    07-26 00:12:18.399: WARN/CameraService(1357): Overlay create failed - retrying
07-26 00:12:18.419: WARN/CameraService(1357): Overlay create failed - retrying
07-26 00:12:18.439: WARN/CameraService(1357): Overlay create failed - retrying
07-26 00:12:18.459: WARN/CameraService(1357): Overlay create failed - retrying
07-26 00:12:18.479: WARN/CameraService(1357): Overlay create failed - retrying
07-26 00:12:18.509: WARN/CameraService(1357): Overlay create failed - retrying
07-26 00:12:18.529: WARN/CameraService(1357): Overlay create failed - retrying
07-26 00:12:18.549: WARN/CameraService(1357): Overlay create failed - retrying
07-26 00:12:18.569: ERROR/CameraService(1357): Overlay Creation Failed!


07-26 00:12:18.609: WARN/System.err(4104): java.lang.RuntimeException: startPreview failed
07-26 00:12:18.609: WARN/System.err(4104):     at android.hardware.Camera.startPreview(Native Method)
07-26 00:12:18.609: WARN/System.err(4104):     at com.petrifiednightmares.transparentphone.main.GenericaCamera.surfaceChanged(GenericaCamera.java:29)
07-26 00:12:18.609: WARN/System.err(4104):     at android.service.wallpaper.WallpaperService$Engine.updateSurface(WallpaperService.java:687)
07-26 00:12:18.609: WARN/System.err(4104):     at android.service.wallpaper.WallpaperService$Engine.attach(WallpaperService.java:749)
07-26 00:12:18.619: WARN/System.err(4104):     at android.service.wallpaper.WallpaperService$IWallpaperEngineWrapper.executeMessage(WallpaperService.java:984)
07-26 00:12:18.619: WARN/System.err(4104):     at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:61)
07-26 00:12:18.619: WARN/System.err(4104):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-26 00:12:18.619: WARN/System.err(4104):     at android.os.Looper.loop(Looper.java:143)
07-26 00:12:18.619: WARN/System.err(4104):     at android.app.ActivityThread.main(ActivityThread.java:4293)
07-26 00:12:18.629: WARN/System.err(4104):     at java.lang.reflect.Method.invokeNative(Native Method)
07-26 00:12:18.629: WARN/System.err(4104):     at java.lang.reflect.Method.invoke(Method.java:507)
07-26 00:12:18.629: WARN/System.err(4104):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
07-26 00:12:18.629: WARN/System.err(4104):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
07-26 00:12:18.629: WARN/System.err(4104):     at dalvik.system.NativeStart.main(Native Method)

推荐答案

它或多或少地遵循了您的代码,并进行了一些更改.

It more or less follows your code with a few changes.

import java.io.IOException;
import android.hardware.Camera;
import android.view.SurfaceHolder;

public class GenericaCamera implements SurfaceHolder.Callback {

    private Camera         cameraDevice        = null;
    private SurfaceHolder  cameraSurfaceHolder = null; 

    // MODIFIED FROM ORIGINAL SEE UPDATE AT BOTTOM
    public GenericaCamera(SurfaceHolder holder)
    {
        cameraSurfaceHolder = holder;
        cameraSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        cameraSurfaceHolder.addCallback(this);
    }

     // Required camera surface holder interface Callback's
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
     {
         Camera.Parameters params = cameraDevice.getParameters();
         Camera.Size       size   = getBestPreviewSize(params,w,h);

         if (size != null)
            params.setPreviewSize(size.width, size.height);
         cameraDevice.startPreview();
     }

     // When the surface is ready then we can build the camera and attach 
     // the camera preview output to the UI holder 
     public void surfaceCreated(SurfaceHolder holder)
     {
        try {

            cameraDevice = Camera.open();  
            cameraDevice.setPreviewDisplay(cameraSurfaceHolder);

        } catch (IOException e) { }

    }

    // Stop the camera preview and dispose of the camera object 
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        if (null == cameraDevice)
            return; 
        cameraDevice.stopPreview(); 
        cameraDevice.release(); 
        cameraDevice = null; 
    }

    public Camera.Size getBestPreviewSize(Camera.Parameters parameters, int w, int h)
    {
        Camera.Size result = null; 

        for (Camera.Size size : parameters.getSupportedPreviewSizes())
        {
            if (size.width <= w && size.height <= h)
            {
                if (null == result)
                result = size; 
            else
            {
                int resultDelta = w - result.width + h - result.height;
                int newDelta    = w - size.width   + h - size.height;

                    if (newDelta < resultDelta)
                result = size; 
            }
            } 
        }
        return result; 
    }

}

更新

进入壁纸代码并弄清楚,仍然存在问题,但至少我让它基本上可以工作,由于推送缓冲区设置,时间顺序很重要

Went into the wallpaper code and figured it out, still problems but at least I got it to basically work, order of when is important because of the push buffers setup

问题

  1. 不在横向模式下,这会导致预览图像失真,相机尚未尝试锁定横向的已知问题

  1. Not in landscape mode, this causes a distorted image to be previewed, known issue of the camera just havent tried to lock into landscape yet

在预览中,如果您使用返回键,一切都会被正确销毁(相机已释放),但如果您设置墙纸,则该类不会调用 onDestroy 方法,因此这意味着您无法获取相机,因为预览实例类的还没有发布呢

In preview if you use back key everything is destroyed properly (camera released) but if you set the wallpaper the class does not call the onDestroy method so this means that you can't get the camera because the preview instance of the class has not released it

它也显示为锁定屏幕图像,不知道如何覆盖它,可能通过意图接收和响应,并在您处于保护/锁定屏幕时将其关闭

It also shows up as the lock screen image, not sure how to override that, probably receive and respond via intents and turn it off when you are in the guard/lock screen

尚未处理可见性事件,因此其他相机类将无法工作,可能会造成不必要的电池消耗等.

Have not handled visibility event, so other camera classes won't work, potential unnecessary battery drain etc.

无论如何,修改如下,以使其至少开始工作

Anyway with all of that said the modifications are as follows to get this to at least start working

在引擎类中,在 onCreate 中从上述类创建相机,任何稍后都会出现问题,因为推送缓冲区设置,即使在以后的 2.3+ 中已弃用,但在旧版本中仍然需要.事实上还没有在 2.2 以上测试过.

In the engine class create the camera from the above class in the onCreate, any later and problems occur because of the push buffers setup, and even though this is deprecated in later 2.3+ it is still required in older versions. Matter of fact have not tested this above 2.2 yet.

@Override
    public void onCreate(SurfaceHolder holder) {
        Log.d("CameraWallpaper","onCreate(SurfaceHolder holder)");
        if (null == GC)
        GC = new GenericaCamera(holder);
    super.onCreate(holder);
}

然后在 GenericCamera 类中改成如下构造函数模式

Then in the GenericCamera class change to the following constructor pattern

public GenericaCamera(SurfaceHolder holder)
{
     cameraSurfaceHolder = holder;
     cameraSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
     cameraSurfaceHolder.addCallback(this);
}

基本上就是这样,至少这应该让你开始,如果你找到任何解决方案 1-4 让社区知道!

That's basically it, at least this should get you started, and if you find any solutions to 1-4 let the community know!

更新 2

Android 3+ 似乎打破了这一点,不知道为什么,因为这些平台的源代码仍然关闭.

It seems that Android 3+ breaks this, not sure why since the source for those platforms is still closed.

因此,最高 2.3 的最终答案是上述工作,但在 3+ 上则不会.

So final answer for upto 2.3 is that above works, but on 3+ it will not.

这篇关于Android - cam.setPreviewDisplay(holder) 遇到 IOError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆