Ява.ленг.RuntimeException: ошибка takePicture

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

если это невозможно, так как я могу справиться с этим исключением ?

btnCapture = (ImageButton) findViewById(R.id.btnCapture);
                final MediaPlayer mp = MediaPlayer.create(CameraLauncherActivity.this, R.raw.button);
                btnCapture.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                            // line where getting RuntimeException
                        camera.takePicture(null, null, mPicture);   

                    }
                });

Log:

02-12 14:48:41.580: E/AndroidRuntime(6997): FATAL EXCEPTION: main
02-12 14:48:41.580: E/AndroidRuntime(6997): java.lang.RuntimeException: takePicture failed
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.hardware.Camera.native_takePicture(Native Method)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.hardware.Camera.takePicture(Camera.java:1126)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.hardware.Camera.takePicture(Camera.java:1071)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at app.cam.shane.CameraLauncherActivity.onClick(CameraLauncherActivity.java:116)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.view.View.performClick(View.java:4223)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.view.View$PerformClick.run(View.java:17275)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.os.Handler.handleCallback(Handler.java:615)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.os.Handler.dispatchMessage(Handler.java:92)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.os.Looper.loop(Looper.java:137)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at android.app.ActivityThread.main(ActivityThread.java:4921)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at java.lang.reflect.Method.invokeNative(Native Method)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at java.lang.reflect.Method.invoke(Method.java:511)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1036)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:803)
02-12 14:48:41.580: E/AndroidRuntime(6997):     at dalvik.system.NativeStart.main(Native Method)

Примечание: как и в Пудинг Камеры, они позволяют пользователю делать непрерывное нажатие на кнопку захвата, но они никогда не будут показывать исключение, если вы сделаете 50 кликов, он захватит 10 или более изображений, каждое изображение после определенного времени, но не показывает исключение, как я получаю в своем коде, таким же образом, как я могу справиться с этим исключением ?

Полный Код:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_camera);

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

            preview=(SurfaceView)findViewById(R.id.surface);     
            previewHolder=preview.getHolder();    
            previewHolder.addCallback(surfaceCallback);    
            previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

            btnCapture = (ImageButton) findViewById(R.id.btnCapture);
            final MediaPlayer mp = MediaPlayer.create(CameraLauncherActivity.this, R.raw.button);
            btnCapture.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mp.start();
                    camera.takePicture(null, null, mPicture);                 
                }
            });


    @Override
    public void onResume() {  
        super.onResume();   
        camera=Camera.open(); 
    }  

    @Override   
    public void onPause() {  
        super.onPause();  
        if (inPreview) {  
        camera.stopPreview();   
        }   
        camera.release();   
        camera=null;   
        inPreview=false;         
    }   


    private Camera.Size getBestPreviewSize(int width, int height,
            Camera.Parameters parameters) {
            Camera.Size result=null;

            for (Camera.Size size : parameters.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);
        }

    private Camera.Size getSmallestPictureSize(Camera.Parameters parameters) {
        Camera.Size result=null;

        for (Camera.Size size : parameters.getSupportedPictureSizes()) {
            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);
    }


    SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback(){

    public void surfaceCreated(SurfaceHolder holder) {     
        try {        
            camera.setPreviewDisplay(previewHolder); 
            }   catch (Throwable t) {   
                Log.e("PreviewDemo-surfaceCallback",
                        "Exception in setPreviewDisplay()", t);
                Toast.makeText(CameraLauncherActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();       
                }     
            }      

    public void surfaceChanged(SurfaceHolder holder,int format, int width,int height) {
        params = camera.getParameters();       
        params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
        Camera.Size size = getBestPreviewSize(width, height, params);  
        Camera.Size pictureSize=getSmallestPictureSize(params);
        if (size != null && pictureSize != null) {      
            params.setPreviewSize(size.width, size.height);
            params.setPictureSize(pictureSize.width,
                    pictureSize.height);
            camera.setParameters(params);       
            camera.startPreview();       
            inPreview=true;                 

            }     
        }      

    public void surfaceDestroyed(SurfaceHolder holder) {

        }   
    };       

    PictureCallback mPicture = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            pictureFile = getOutputMediaFile();
            camera.startPreview();
            if (pictureFile == null) {
                return;
            }
            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
            } catch (FileNotFoundException e) {

            } catch (IOException e) {
            }
        }
    };

    static File getOutputMediaFile() {

        /* yyyy-MM-dd'T'HH:mm:ss.SSSZ */
        timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
        .format(new Date());

        // file name
        mediaFile = new File(LoginActivity.mediaStorageDir.getPath() + File.separator
                + "IMG_" + timeStamp + ".jpg");

        return mediaFile;

    }


}

5 ответов


во-первых, поймать ваши исключения в onPictureTaken, оставляя пустые разделы catch не является хорошей практикой. Затем я бы добавил флаг, который предотвратит вызов takePicture () во время сохранения предыдущего изображения. Позже в вашей кнопке onClick вы проверите, можно ли вызвать takePicture().

  1. объявить флаг в качестве члена вашей деятельности:

    private boolean safeToTakePicture = false;
    
  2. на surfaceChanged(), просто установите флаг в true после вызова startPreview():

    camera.startPreview();
    safeToTakePicture = true;
    
  3. в своем onClick() слушатель проверить флаг и сфотографировать, если ok, чтобы сделать это:

    if (safeToTakePicture) {
        mp.start();
        camera.takePicture(null, null, mPicture); 
        safeToTakePicture = false;
    }
    
  4. на onPictureTaken(), установите флаг снова в true после сохранения изображения (и добавьте печать исключений):

    PictureCallback mPicture = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            pictureFile = getOutputMediaFile();
            camera.startPreview();
    
            if (pictureFile == null) {
                //no path to picture, return
                safeToTakePicture = true;
                return;
            }
            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();              //<-------- show exception
            } catch (IOException e) {
                e.printStackTrace();              //<-------- show exception
            }
    
            //finished saving picture 
            safeToTakePicture = true;
        }
    };
    

Примечания: Как говорят врачи,"предварительный просмотр должен быть запущен, прежде чем вы можете сделать снимок.", поэтому возможное повышение было бы использовать setPreviewCallback () для регистрации обратного вызова, который будет вызываться при наличии данных предварительного просмотра, и установите флаг true при вызове onPreviewFrame.


у меня также была аналогичная проблема. позже я нашел startPreview - Это очень важно.

_camera.startPreview() очень важно перед проверкой takePicutre пункт 5 и 6 по этой ссылке.


может быть много причин для этого в моем случае я пытался сделать фотографию без предварительного просмотра (скрытая фотография), и я использовал SurfaceView, поэтому я заменил его с SurfaceTexture

SurfaceTexture surfaceTexture = new SurfaceTexture(10);
camera.setPreviewTexture(surfaceTexture);

и проблема была решена... P. S я получал эту ошибку только на устройствах выше 6.0


ты забыл назвать startPreview() на камеру?

посмотреть здесь для получения дополнительной информации.


этот метод поможет вам в попытках решить проблему.

private void safeCameraOpen(int id) {

        try {
            releaseCameraAndPreview();
            mCamera = Camera.open(id);
        } catch (Exception e) {
            Log.e(getString(R.string.app_name), "failed to open Camera");
            e.printStackTrace();
        }

    }

private void releaseCameraAndPreview() {
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }