Android: Camera: jpeg call back picture data null

2019-09-08 16:51发布

问题:

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

回答1:

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.



回答2:

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.