Android - cam.setPreviewDisplay (держатель), работающий в IOError - PullRequest
1 голос
/ 26 июля 2011

Я пытаюсь использовать изображение с камеры как часть живых обоев.

В заявленном мной движке у меня есть этот код:

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 ();

Когда я запускаюэто я получаю: java.io.IOException: setPreviewDisplay failed

Теперь я получаю это исключение:

    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)

Ответы [ 2 ]

5 голосов
/ 26 июля 2011

Более или менее следует вашему коду с небольшими изменениями.

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; 
    }

}

Обновление

Пошел в код обоев иразобрался, все еще проблемы, но, по крайней мере, я заставил его работать в основном, порядок важности из-за настройки push-буферов

Проблемы

  1. Не в ландшафтном режиме, это приводит к предварительному просмотру искаженного изображения, известная проблема с камерой, которая еще не пыталась зафиксировать пейзаж

  2. В режиме предварительного просмотра, если вы нажмете клавишу возврата, все будет уничтожено должным образом (камера отпущена)но если вы устанавливаете обои, класс не вызывает метод onDestroy, так что это означает, что вы не можете получить камеру, потому что экземпляр предварительного просмотра класса не выпустил ее

  3. Это такжеотображается как изображение экрана блокировки, не знаю, как его переопределить, возможно, получайте и отвечайте через намерения и выключайте его, когда находитесь на экране защиты / блокировки

  4. Не обработано vСобытие isibility, поэтому другие классы камер не будут работать, потенциальная ненужная разрядка батареи и т. д.

В любом случае, со всем вышеперечисленным изменениями необходимо выполнить следующие действия, чтобы это хотя бы начало работать

В классе движка создайте камеру из вышеупомянутого класса в onCreate, любое позднее, и проблемы возникают из-за настройки push-буферов, и хотя это не рекомендуется в более поздних 2.3+, это все еще требуется в более старых версиях.На самом деле это еще не проверено выше 2.2.

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

Затем в классе GenericCamera перейдите к следующему шаблону конструктора.4 Сообщите сообществу!

Обновление 2

Кажется, что Android 3+ ломает это, не знаю почему, поскольку исходный код для этих платформ все еще закрыт.

Итак, окончательноОтвет до 2.3 - выше работает, а на 3+ - нет.

0 голосов
/ 11 марта 2015

Я видел следующую ошибку, дающую мне java.io.IOException: setPreviewDisplay failed:

Если вы делаете видео и фото, есть две функции: camera.unlock () и камера.reconnect () .Вы должны camera.unlock () перед записью видео и camera.reconnect () перед фотографированием.

...