Android — ошибка поверхности камеры

У меня есть этот код для моего приложения, он не показывает никаких ошибок, но каждый раз, когда я запускаю его на своем телефоне, он вылетает. Кто-нибудь имеет представление об этом? Спасибо

public class CameraView extends Activity implements SurfaceHolder.Callback,OnClickListener {
        static final int FOTO_MODE = 0;
        private static final String TAG = "CameraTest";
        Camera mCamera;
        boolean mPreviewRunning = false;
        private Context mContext = this;

        public void onCreate(Bundle icicle) {
            super.onCreate(icicle);

            Log.e(TAG, "onCreate");

            Bundle extras = getIntent().getExtras();

            getWindow().setFormat(PixelFormat.TRANSLUCENT);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
            setContentView(R.layout.camera_surface);
            mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
            mSurfaceView.setOnClickListener(this);
            mSurfaceHolder = mSurfaceView.getHolder();
            mSurfaceHolder.addCallback(this);
            mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
        //private SurfaceView mSurfaceView;
        //private SurfaceHolder mSurfaceHolder;

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

        Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
            public void onPictureTaken(byte[] imageData, Camera c) {

                if (imageData != null) {

                    Intent mIntent = new Intent();

                    StoreByteImage(mContext, imageData, 50,
                            "ImageName");
                    mCamera.startPreview();

                    setResult(FOTO_MODE, mIntent);
                    finish();

                }
            }
        };

        protected void onResume() {
            Log.e(TAG, "onResume");
            super.onResume();
        }

        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
        }

        protected void onStop() {
            Log.e(TAG, "onStop");
            super.onStop();
        }

        public void surfaceCreated(SurfaceHolder holder) {
            Log.e(TAG, "surfaceCreated");
            mCamera = Camera.open();

        }

        private Camera.Size getBestPreviewSize(int width, int height)
        {
            Camera.Size result=null;    
            Camera.Parameters p = mCamera.getParameters();
            for (Camera.Size size : p.getSupportedPreviewSizes()) {
                if (size.width<=width && size.height<=height) {
                    if (result==null) {
                        result=size;
                    } else {
                        int resultArea=result.width*result.height;
                        int newArea=size.width*size.height;

                        if (newArea>resultArea) {
                            result=size;
                        }
                    }
                }
            }
            return result;
        }

        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
            Log.e(TAG, "surfaceChanged");

            // XXX stopPreview() will crash if preview is not running
            if (mPreviewRunning) {
                mCamera.stopPreview();
            }

            Camera.Parameters p = mCamera.getParameters();
            Camera.Size bestSize = getBestPreviewSize(w, h);
            p.setPreviewSize(bestSize.width, bestSize.height);
            mCamera.setParameters(p);
            try {
                mCamera.setPreviewDisplay(holder);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            mCamera.startPreview();
            mPreviewRunning = true;
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            Log.e(TAG, "surfaceDestroyed");
            mCamera.stopPreview();
            mPreviewRunning = false;
            mCamera.release();
        }

        private SurfaceView mSurfaceView;
        private SurfaceHolder mSurfaceHolder;

        public void onClick(View arg0) {

            mCamera.takePicture(null, mPictureCallback, mPictureCallback);

        }

        public static boolean StoreByteImage(Context mContext, byte[] imageData,
                int quality, String expName) {

            File sdImageMainDirectory = new File("/sdcard");
            FileOutputStream fileOutputStream = null;
            String nameFile;
            try {

                BitmapFactory.Options options=new BitmapFactory.Options();
                options.inSampleSize = 5;

                Bitmap myImage = BitmapFactory.decodeByteArray(imageData, 0,
                        imageData.length,options);


                fileOutputStream = new FileOutputStream(
                        sdImageMainDirectory.toString() +"/image.jpg");


                BufferedOutputStream bos = new BufferedOutputStream(
                        fileOutputStream);

                myImage.compress(CompressFormat.JPEG, quality, bos);

                bos.flush();
                bos.close();

            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return true;
        }

        /*@Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
            // TODO Auto-generated method stub
            Log.e(TAG, "surfaceChanged");

            // XXX stopPreview() will crash if preview is not running
            if (mPreviewRunning) {
                mCamera.stopPreview();
            }

            Camera.Parameters p = mCamera.getParameters();
            p.setPreviewSize(w, h);
            mCamera.setParameters(p);
            try {
                mCamera.setPreviewDisplay(holder);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            mCamera.startPreview();
            mPreviewRunning = true;
        }

        @Override
        public void surfaceCreated(SurfaceHolder arg0) {
            // TODO Auto-generated method stub
            Log.e(TAG, "surfaceCreated");
            mCamera = Camera.open();

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder arg0) {
            // TODO Auto-generated method stub
            Log.e(TAG, "surfaceDestroyed");
            mCamera.stopPreview();
            mPreviewRunning = false;
            mCamera.release();

        }*/
}

person hectichavana    schedule 27.04.2011    source источник
comment
Что значит "вылетает"? Есть ли какие-либо подробные сообщения в системном журнале?   -  person dronus    schedule 04.05.2011


Ответы (3)


Знаете ли вы, где на самом деле возникает ошибка (т.е. какой вывод вы видите в окне logcat?)

Мое дикое предположение заключается в том, что эта строка вызывает проблему:

p.setPreviewSize(w, h)

Вы можете установить размер предварительного просмотра только на один из размеров, поддерживаемых вашим устройством — проверьте метод getSupportedPreviewSizes() в Camera.Parameters и выберите наиболее близкое соответствие для вашего вида:

private Camera.Size getBestPreviewSize(int width, int height)
{
    Camera.Size result=null;    
    Camera.Parameters p = camera.getParameters();
    for (Camera.Size size : p.getSupportedPreviewSizes()) {
        if (size.width<=width && size.height<=height) {
            if (result==null) {
                result=size;
            } else {
                int resultArea=result.width*result.height;
                int newArea=size.width*size.height;

                if (newArea>resultArea) {
                    result=size;
                }
            }
        }
    }
    return result;
}

(код выше из @seantron: Изображение искажено камерой и getOptimalPreviewSize)

person Scottie    schedule 03.05.2011
comment
Я не сталкиваюсь с какими-либо ошибками с моим эмулятором, только когда я монтирую приложение на свое устройство. Так что я должен добавить этот метод, а затем вызвать вместо setPreviewSize или что? Когда я пытаюсь написать метод, возникает ошибка с 'camera.getParameters();' - person hectichavana; 03.05.2011
comment
Эмулятор не привередлив к размеру предварительного просмотра, он будет эмулировать все, что вы попросите. Замените camera на mCamera во фрагменте выше, затем вызовите этот метод перед вызовом setPreviewSize. Вы хотите вызвать setPreviewSize с результатом, возвращаемым из getBestPreviewSize, т.е. setPreviewSize(result.width, result.height) - person Scottie; 03.05.2011
comment
Я получил ошибку при вызове этих методов; p.getBestPreviewSize(ш, ч); p.setPreviewSize (результат.w, результат.h); любая идея? - person hectichavana; 03.05.2011
comment
Приведенный выше метод bestPreviewSize необходимо скопировать в ваш класс; это не метод Camera.Parameters. Ваш код будет выглядеть примерно так: Camera.Size bestSize = bestPreviewSize(w, h);, за которым следует p.setPreviewSize(bestSize.w, bestSize.h);. - person Scottie; 03.05.2011
comment
Я обновил свой код, как вы предложили, ошибок не обнаружено, но приложение разбилось.. хммм, что вы думаете? - person hectichavana; 03.05.2011
comment
Трудно узнать без дополнительной информации. Поставьте точку останова на строку p.setPreviewSize(bestSize.width, bestSize.height);, а затем пройдитесь по строкам кода, пока ваше приложение не выйдет из строя, чтобы вы могли точно определить фактическую строку, вызывающую проблему. Проверьте окно logcat в перспективе Debug на наличие ошибок, выделенных красным цветом — некоторые строки должны объяснять, почему приложение дает сбой. Кстати, на какую версию/уровень API Android вы ориентируетесь и на каком оборудовании? - person Scottie; 03.05.2011
comment
мой logcat показывает, что сбой вызван этой строкой: «for (Camera.Size size: p.getSupportedPreviewSizes())», затем следует «Camera.Size bestSize = getBestPreviewSize (w, h);» Я все еще тестирую эмулятор, уровень API 7 - person hectichavana; 03.05.2011
comment
По-видимому, getSupportedPreviewSizes может возвращать null на эмуляторе, хотя в спецификации сказано, что всегда должен возвращаться хотя бы один размер предварительного просмотра. Попробуйте ввести оператор и IF, чтобы пропустить код для установки наилучшего размера предварительного просмотра, когда не возвращаются поддерживаемые размеры предварительного просмотра, или просто попробуйте запустить код на своем телефоне. - person Scottie; 04.05.2011
comment
Большое спасибо, это работает на моем телефоне, но вид был немного странным. Вы можете посмотреть это здесь: yfrog.com/gyz4q1j, возможно, вы понимаете, в чем проблема - person hectichavana; 05.05.2011
comment
Это потому, что дисплей камеры повернут на 90 градусов, я думаю, по умолчанию предполагается, что камера используется в ландшафтном режиме, а не в портретном. Один из способов исправить это — вызвать mCamera.setDisplayOrientation(90);, однако при попытке сохранить растровое изображение возникают побочные эффекты: ссылка - person Scottie; 06.05.2011
comment
хорошо, я попытаюсь вызвать метод. Не волнуйтесь, я не использую этот CameraView не для фотосъемки, а для базового просмотра дополненной реальности. - person hectichavana; 06.05.2011

Surround setPreview() камеры с блоком try & catch, может это сработает

person Community    schedule 27.04.2011
comment
Я уже понял это, попробуйте { mCamera.setPreviewDisplay(holder); } catch (IOException e) { // Автоматически сгенерированный блок catch TODO e.printStackTrace(); } на эмуляторе работает, а на телефоне нет, странно :/ - person hectichavana; 27.04.2011
comment
тогда прости, приятель, я тоже не знаю - person ; 27.04.2011

У меня была аналогичная проблема, и причиной была реализация метода surfaceDestroyed (держатель SurfaceHolder). Когда я закомментировал код, все было хорошо.

person BluJ IT    schedule 28.05.2011