java.lang.RuntimeException: takePicture failed

48,463

Solution 1

Firstly, catch your exceptions in onPictureTaken, leaving empty catch sections is not a good practice. Then, I would add a flag that would prevent from calling takePicture() while previous picture is being saved. Later in your button onClick you would check if it's ok to call takePicture().

  1. Declare a flag as a member of your Activity:

    private boolean safeToTakePicture = false;
    
  2. In surfaceChanged(), just set the flag to true after calling startPreview():

    camera.startPreview();
    safeToTakePicture = true;
    
  3. In your onClick() listener check the flag and take picture if ok to do so:

    if (safeToTakePicture) {
        mp.start();
        camera.takePicture(null, null, mPicture); 
        safeToTakePicture = false;
    }
    
  4. In onPictureTaken(), set the flag again to true after picture has been saved (and add exception printing):

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

NOTES: As the docs say, "Preview must be started before you can take a picture.", so possible enhancement would be to use setPreviewCallback() to register callback that will be called when preview data is available, and set the flag to true when onPreviewFrame is called.

Solution 2

I also had the similar issue. later i found startPreview is very important.

_camera.startPreview() is very important before the takePicutre checkout the point 5 and 6 in this link.

Solution 3

There can be many reasons for this in my case i was trying to take photo without preview (hidden photo) and i was using SurfaceView, So i replaced it with SurfaceTexture

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

and the problem was solved... P.S I was getting this error only on Above 6.0 devices

Solution 4

Did you forget to call startPreview() on the Camera?

See here for more information.

Share:
48,463

Related videos on Youtube

Sun
Author by

Sun

Updated on July 09, 2022

Comments

  • Sun
    Sun almost 2 years

    when i do continuous click on Capture button (without any break), getting Runtime Exception how can i resolve this issue ?

    if its not possible so how may i handle this Exception ?

    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$3.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)
    

    Note:- Like in Pudding Camera, they allow user to do continuous tap on Capture button, but they will never show exception, if you do 50 clicks it will capture 10 or more images, each image after specific time but not showing exception, like i am getting in my code, in a same way how can i handle this exception ?

    Complete Code:

    @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;
    
        }
    
    
    }
    
    • Seshu Vinay
      Seshu Vinay over 10 years
      Did you add required permissions in the manifest?
    • Sun
      Sun over 10 years
      everything works fine just want to do control on continuous click and want to control over exception
    • Kishore
      Kishore over 10 years
      U have to call startPreview() after takePicture()
    • Melquiades
      Melquiades over 10 years
      1. Please add onPictureTaken() code in your question. 2. When is onTouchEvent() used? 3. Do you want to take picture by pressing button only? 4. Is RuntimeException happening if you press the button once?
    • Sun
      Sun over 10 years
      @Melquiades hello bro i posted complete code please check now, getting RuntimeException when pressing multiple times without any break otherwise works fine
    • Melquiades
      Melquiades over 10 years
      You could use flag to limit calling takePicture() to the speed with which your images are being saved. More details in the answer.
  • Sun
    Sun over 10 years
    before takePicture(..) where in onTouchEvent(,..) or capture button ?
  • Sun
    Sun over 10 years
    such a amazing solution :) you are just genius.. nice explanation, and one small question what if i also want to use Camera's default button to capture image, like in pudding camera
  • Ahmad Arslan
    Ahmad Arslan almost 10 years
    why my implement method didt call it start ? :( surfaceChanged()
  • Erum
    Erum over 9 years
    @Melquiades this code is not working inside Thread and i m getting exception pastie.org/9583142 its taking fist image fine but after first image it gets crashed
  • Melquiades
    Melquiades over 9 years
    @ErumHannan, can you post a new question on SO with your code, and notify me, I'll have a look.
  • Erum
    Erum over 9 years
    i have resolved this issue but still after taking pictures in loop i m starting another activity but from new activity when trying to hit back key to move back towards camera activity its crashing my app because onStop has been called and it releases the camera but onStart i have start the camera again but its not working @Melquiades
  • Erum
    Erum over 9 years
  • John
    John over 9 years
    I used Camera.setPreviewCallback()..it worked fine for me...thanks Melquiades
  • Muhammad Babar
    Muhammad Babar over 9 years
    calling camera.startPreview() before takePicture did the trick!
  • Patrick
    Patrick over 5 years
    @Sun yes, you need to call camera.startPreview() when the saving job is done (eg. in onPictureTaken()), else the camera won't allow you to take another image
  • Castor
    Castor almost 5 years
    @Melquiades What is mp?
  • Melquiades
    Melquiades almost 5 years
    @SoftDev MediaPlayer - see in original question