0

I have the below code blocks to capture a picture from the front camera and store it onto storage. The below code is working perfectly for all the devices I tried (Samsung Galaxy S2, Note 2, Micromax Canvas 2, HD, Sony Xperia U) but the "data" returned for the jpegcallback is always null on HTC One X. Any ideas why?

public void takePicture () {
        Log.d("camera","taking picture");
        // do we have a camera?
        if (cameraIsOk()) {
            Log.d("camera","waiting 1");

            try {
                synchronized (this) {
                   wait(2000);
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                Log.d("camera", "Waiting didnt work!!");
                e.printStackTrace();
            }
            if (myCamera == null) 
                myCamera = Camera.open(camId);

            if (myCamera != null)
            {
                Log.d("camera","surface view");
                SurfaceView surfaceView = new SurfaceView(context);
                surfaceView.setFocusable(true);
                Log.d("camera","getting holder");
                SurfaceHolder holder = surfaceView.getHolder();
                Log.d("camera","add callback");
                holder.addCallback(this);
                Log.d("camera","set type");
                holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

                try {
                    Log.d("camera","get parameters");
                    Camera.Parameters parameters = myCamera.getParameters();
                    Log.d("camera","get supported preview size");
                    List<Size> sizes = parameters.getSupportedPreviewSizes();
                    Size optimalSize = GBCameraUtil.getOptimalPreviewSize(sizes, 1024, 768);

                    int sdkBuildVersion = Integer.parseInt( android.os.Build.VERSION.SDK );

                    if (sdkBuildVersion < 5 || usingLandscape) 
                    {
                        // Picture size should be landscape
                        if (optimalSize.width < optimalSize.height || usingLandscape)
                            parameters.setPictureSize( optimalSize.height, optimalSize.width );
                        else
                            parameters.setPictureSize( optimalSize.width, optimalSize.height );
                    }
                    else
                    {
                        // If the device is in portraint and width > height, 
                        // or if the device is in landscape and height > height, so we need to rotate them.
                        switch (context.getResources().getConfiguration().orientation) {
                        case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE :
                            if (optimalSize.height > optimalSize.width ) {
                                parameters.setRotation(camId == GBCameraUtil.findFrontFacingCamera() ? 270 : 90);
                            }

                            break;                               
                        case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT :                     
                            if (optimalSize.width > optimalSize.height) {
                                parameters.setRotation(camId == GBCameraUtil.findFrontFacingCamera() ? 270 : 90);
                            }

                            break;                               
                        }  

                        parameters.setPictureSize (optimalSize.width, optimalSize.height);
                    }
                    Log.d("camera","set param");
                    myCamera.setParameters(parameters); 
                    Log.d("camera","set preview disp");

                    myCamera.setPreviewDisplay(holder);
                    Log.d("camera","start preview");
                    myCamera.startPreview(); 
                    Log.d("camera","take picture");
                    myCamera.takePicture(null, null, getJpegCallback());


                } catch (Exception e) {
                    // Sorry, nothing to do
                }
            }
        }
    }

    private PictureCallback getJpegCallback(){
        PictureCallback jpeg=new PictureCallback() {   
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                myCamera.stopPreview();
                mPreviewRunning = false;
                Log.d("camera","pic taken");

                if (data != null) {
                    Toast.makeText(context, "data not null ", Toast.LENGTH_LONG).show();
                    Log.d("camera","data not null. Filename is :" + fileName);


                    FileOutputStream fos;
                    try {
                        if (fileName.equals("")) {
                            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
                            String date = dateFormat.format(new Date());
                            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                                fileName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "picture" + date + ".jpg";
                            }
                            else{
                                Toast.makeText(context, "storing to internal " , Toast.LENGTH_LONG).show();
                                //  fileName = Environment.getDataDirectory().getAbsolutePath() + "/" + "picture" + date + ".jpg";
                                fileName = context.getFilesDir().getAbsolutePath()+ "/" + "unlocked" + date + ".jpg";
                            }
                            Toast.makeText(context, "filename " + fileName, Toast.LENGTH_LONG).show();
                            Log.d("camera","filename is : " + fileName);
                        }
                        Log.d("camera","coming here");
                        fos = new FileOutputStream(new File(fileName));
                        Log.d("camera","writing data");

                        fos.write(data);
                        Log.d("camera","written data");
                        fos.close();
                    }  catch (IOException e) {
                        //do something about it
                        Log.d("camera","some exception"+ e);
                    }


                }
                else
                    Toast.makeText(context, "data  null " , Toast.LENGTH_LONG).show();

                myCamera.release();
                myCamera = null;    
            }
        };

        return jpeg;
    }
user2349990
  • 386
  • 4
  • 19
  • This seems relevant to http://stackoverflow.com/questions/5946837/android-raw-image-callback-supported-devices – linakis Oct 08 '13 at 16:00
  • No.. its not.. The other one is a raw data callback.. But in mine, the jpeg data callback is the one returning null. – user2349990 Oct 08 '13 at 16:10

2 Answers2

0

Maybe the problem is that you asked the list of supported preview sizes. Could it be that supported picture sizes are different on HTC One X? This is not the problem here. See another answer.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • I even tried getting the supported picture size by using getSupportedPictureSize andthen assigning the output to the setPictureSize. Even doing so gave me the same null data. – user2349990 Oct 09 '13 at 04:42
  • OK, what picture size did you finally request? – Alex Cohn Oct 09 '13 at 06:48
  • 320x480.. I'm guessing that the problem is with htc phones alone. I just started a camera intent to take a picture.. I see that after I click on the camera button, it takes the picture but does not return it to the calling activity until the user clicks on the "tick" mark that follows after clicking the "take picture" button. Since in mine I'm waiting for the callback just after taking picture, it is not getting the required data. Until there is a way to automatically trigger the "tick mark", the data will be returned as null, mostly. – user2349990 Oct 31 '13 at 06:38
  • I had only few moments with this device, but takePicture()/onPictureTaken() worked smoothely. Maybe you put the camera in special focusing mode? – Alex Cohn Nov 03 '13 at 14:01
  • **PS** I just noticed that your `onPictureTaken()` calls `camera.stopPreview()`. To the best of my knowledge, it should not. – Alex Cohn Nov 03 '13 at 14:03
  • Where else should the stopPreview() be called? – user2349990 Nov 04 '13 at 10:24
  • See http://developer.android.com/reference/android/hardware/Camera.html#takePicture(android.hardware.Camera.ShutterCallback,%20android.hardware.Camera.PictureCallback,%20android.hardware.Camera.PictureCallback): _This method is only valid when preview is active (after startPreview()). Preview will be stopped after the image is taken; callers must call startPreview() again if they want to re-start preview or take more pictures. This should not be called between start() and stop()._ – Alex Cohn Nov 04 '13 at 14:29
0

I noticed that your onPictureTaken() calls camera.stopPreview(). To the best of my knowledge, it should not.

See Camera.takePicture:

This method is only valid when preview is active (after startPreview()). Preview will be stopped after the image is taken; callers must call startPreview() again if they want to re-start preview or take more pictures. This should not be called between start() and stop().

The bold is mine. You should not call camera.stopPreview() after you call camera.takePicture(). The system will do that for you. It happens so, some devices may forgive an unexpected call, but HTC One X will not.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307