Android摄像头,onPictureTaken(byte []的imgData,相机摄像头)方法和放大器; PictureCallback从来不叫摄像头、放大器、不叫、相机

2023-09-07 08:38:46 作者:小仙女

我有一个自定义的摄像头应用程序,即previews摄像机的视频输出上SurfaceView,并试图拍照,该图片应该将处理由xzing扫描仪API脱$ C C任何酒吧$ C $ $ CS的形象。

我的应用程序previews正确,不抛出任何错误或预期,但是我onPictureTaken(byte []的imgData,相机摄像头)方法和放大器; PictureCallback是从来不叫,所以我无法获取图像和放大器;继续进一步的扫描。

下面是实际$ C $下的活动,需要摄像机逻辑的照顾。该onPictureTaken(byte []的imgData,相机摄像头)方法和放大器; PictureCallback在这个类(ScanVinFromBar codeActivity.java)见一击:

 包com.ty.tyownerspoc.bar code;

进口的java.io.File;
进口java.io.FileOutputStream中;
进口java.io.IOException异常;
进口java.text.SimpleDateFormat的;
进口java.util.Date;
进口com.google.zxing.BinaryBitmap;
进口com.google.zxing.ChecksumException;
进口com.google.zxing.FormatException;
进口com.google.zxing.MultiFormatReader;
进口com.google.zxing.NotFoundException;
进口com.google.zxing.RGBLuminanceSource;
进口com.google.zxing.Reader;
进口com.google.zxing.Result;
进口com.google.zxing.common.HybridBinarizer;
进口android.annotation.Sup pressLint;
进口android.app.Activity;
进口android.content.pm.PackageManager;
进口android.content.res.Configuration;
进口android.graphics.Bitmap;
进口android.graphics.BitmapFactory;
进口android.graphics.ImageFormat;
进口android.graphics.Matrix;
进口android.graphics.Point;
进口android.hardware.Camera;
进口android.hardware.Camera.CameraInfo;
进口android.hardware.Camera.Parameters;
进口android.hardware.Camera.PictureCallback;
进口android.os.Bundle;
进口android.os.Environment;
进口android.util.Log;
进口android.view.Display;
进口android.view.SurfaceView;
进口android.view.View;
进口android.widget.FrameLayout;
进口android.widget.TextView;
进口android.widget.Toast;
进口com.ty.tyownerspoc.R;

公共类ScanVinFromBar codeActivity延伸活动{

    私人相机globalCamera;
    私人诠释cameraId = 0;
    私人TextView的VINtext = NULL;
    私人查看scanButton = NULL;
    //位图从相机
    私人位图bmpOfTheImageFromCamera = NULL;
    //全局标志照相机是否已经检测
    私人布尔isThereACamera = FALSE;
    // surfaceView为preVIEW对象
    私人的FrameLayout frameLayoutBar codeScanner = NULL;
    私人相机preVIEW newCamera preVIEW = NULL;
    私人SurfaceView surfaceViewBar codeScanner = NULL;
    私人INT计数器= 0;
    私人挥发性布尔finishedPictureTask = FALSE;
    / *
     *这个方法,发现FEATURE_CAMERA,打开相机,设置参数,
     *添加相机preVIEW布局,设置相机表面支架,启动preVIEW
     * /
    私人无效initializeGlobalCamera(){
        尝试 {
            如果(!getPackageManager()。hasSystemFeature(
                    PackageManager.FEATURE_CAMERA)){
                Toast.makeText(这一点,没有摄像头在此设备上,
                        Toast.LENGTH_LONG).show();
            }其他{//检查前置摄像头,并获得ID
                cameraId = findFrontFacingCamera();
                如果(cameraId℃,){

                    Toast.makeText(这一点,没有前置摄像头发现。
                            Toast.LENGTH_LONG).show();
                } 其他 {

                    Log.d(ClassScanViewBar codeActivity
                            摄像头被发现,ID:+ cameraId);
                    //摄像头被发现,设置全局相机标志设置为true
                    isThereACamera = TRUE;
                    // 打开
                    globalCamera = Camera.open(cameraId);

                    //传递surfaceView到相机preVIEW
                    newCamera preVIEW =新相机preVIEW(这一点,globalCamera);
                    //通过摄像头preVIEW来布局
                    frameLayoutBar codeScanner.addView(newCamera preVIEW);
                    尝试 {
                        globalCamera
                                .SET previewDisplay(surfaceViewBar codeScanner
                                        .getHolder());
                    }赶上(IOException异常E){
                        // TODO自动生成的catch块
                        e.printStackTrace();
                    }
                    // preVIEW
                    globalCamera.start preVIEW();

                    Log.d(ClassScanViewBar codeActivity
                            摄像头打开和放大器; previewing);
                }
            } //结束否则,检查前置摄像头
        } //结束试
        赶上(例外EXC){

            //如果异常释放资源和放大器;清理
            如果(globalCamera!= NULL){
                globalCamera.stop preVIEW();
                globalCamera.set previewCallback(空);
                globalCamera.release();
                globalCamera = NULL;

            }
            Log.d(ClassScanViewBar codeActivity initializeGlobalCamera()异常:,
                    exc.getMessage());
        } //结束抓
    }

    //的onCreate,实​​例化布局和放大器; surfaceView用于视频preVIEW
    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_bar code_vin_scanner);
        Log.d(ClassScanViewBar codeActivity,的onCreate);

        //创建surfaceView的摄像机图像的previewing
        frameLayoutBar codeScanner =(的FrameLayout)findViewById(R.id.FrameLayoutFor preVIEW);
        surfaceViewBar codeScanner =(SurfaceView)findViewById(R.id.surfaceViewBar codeScanner);

        initializeGlobalCamera();

        //创建文本区与放大器;扫描按钮
        VINtext =(TextView中)findViewById(R.id.mytext);
        scanButton = findViewById(R.id.webbutton);
        //在点击监听器,的onClick拍照
        scanButton.setOnClickListener(新View.OnClickListener(){
            公共无效的onClick(视图v){
                尝试 {

                    //如果为true拍照
                    如果(isThereACamera){
                        Log.d(ClassScanViewBar codeActivity
                                setOnClickListener()isThereACamera:+ isThereACamera);

                        //设置图片格式为JPEG,每次makesure JPEG回调被称为
                         参数参数= globalCamera.getParameters();
                         parameters.setPictureFormat(ImageFormat.JPEG);
                         globalCamera.setParameters(参数);
                         //采取事先知情同意,应该调用回调
                        globalCamera.takePicture(NULL,NULL,jpegCallback);
                        //等待1秒,比重新启动preVIEW
                        视频下载(1000);
                        //停止
                        globalCamera.stop preVIEW();
                        //再次启动previewing onthe SurfaceView的情况下使用要采取另一种PIC /扫描
                        globalCamera.start preVIEW();

                    }

                } //结束试
                赶上(例外EXC){

                    //如果异常释放资源和放大器;清理
                    如果(globalCamera!= NULL){
                        globalCamera.stop preVIEW();
                        globalCamera.set previewCallback(空);
                        globalCamera.release();
                        globalCamera = NULL;

                    }
                    Log.d(ClassScanViewBar codeActivity setOnClickListener()exceprtion:,
                            exc.getMessage());
                } //结束抓

            } //上单击结束
        }); //结束OnClickListener()实现

    } //结束的onCreate

    @覆盖
    保护无效onResume(){

        Log.d(ClassScanViewBar codeActivity,onResume()globalCamera:,
                将String.valueOf(globalCamera));

        如果(globalCamera!= NULL){
            //开始preVIEW
            globalCamera.start preVIEW();
        } 其他 {
            initializeGlobalCamera();
        }

        super.onResume();
    }

    @覆盖
    保护无效的onStop(){

        如果(globalCamera!= NULL){
            globalCamera.stop preVIEW();
            globalCamera.set previewCallback(空);
            globalCamera.release();
            globalCamera = NULL;
        }
        super.onStop();
    }

    //使用takePicture回调()
    PictureCallback jpegCallback =新PictureCallback(){



        公共无效onPictureTaken(byte []的imgData,相机摄像头){
            BinaryBitmap位= NULL;
            尝试 {



                Log.d(ClassScanViewBar codeActivity,onPictureTaken());

                //保存图片到SD卡
                savePicture(imgData);

                //从相机为imageData位图
                bmpOfTheImageFromCamera = BitmapFactory.de codeByteArray(
                        imgData,0,imgData.length);


                如果(bmpOfTheImageFromCamera!= NULL){
                    //银河S3,不正确的轮换问题旋转到正确的旋转
                    字模=新的Matrix();
                    matrix.postRotate(90);
                    位图rotatedBitmap = Bitmap.createBitmap(bmpOfTheImageFromCamera,0,0,bmpOfTheImageFromCamera.getWidth(),bmpOfTheImageFromCamera.getHeight(),矩阵,真);
                    //位图转换成二进制位图
                    位= cameraBytesToBinaryBitmap(rotatedBitmap);


                    如果(位图!= NULL){
                        //德$ C C的VIN $
                        字符串VIN =去codeBitmapToString(位);
                        Log.d(*** ClassScanViewBar codeActivity,onPictureTaken():VIN,
                                VIN);
                        VINtext.setText(VIN);
                    } 其他 {
                        Log.d(ClassScanViewBar codeActivity,onPictureTaken():位图=,将String.valueOf(位图));

                    }
                } 其他 {
                    Log.d(ClassScanViewBar codeActivity,onPictureTaken():bmpOfTheImageFromCamera =,
                            将String.valueOf(bmpOfTheImageFromCamera));

                }
            } //结束试

            赶上(例外EXC){
                exc.getMessage();

                Log.d(ClassScanViewBar codeActivity,scanButton.setOnClickListener():异常=,
                        exc.getMessage());
            }

        } //结束onPictureTaken()
    }; // jpegCallback实施


    / *
     *创建savePicture(byte []的数据)进行测试
     * /
    公共无效savePicture(byte []的数据)
    {
        Log.d(ScanVinFromBar codeActivity,savePicture(byte []的数据));
        SimpleDateFormat的日期格式=新的SimpleDateFormat(YYYYMMDDHHMMSS);
        字符串日期= dateFormat.format(新日期());
        字符串photoFile =图片_+专柜+_+日期+.JPG;

        文件sdDir =环境
                  .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);


        字符串文件名= sdDir +文件分割符+ photoFile;

        文件PictureFile的=新的文件(文件名);

        尝试 {
          FileOutputStream中FOS =新的FileOutputStream(PictureFile的);
          fos.write(数据);
          fos.close();

          Toast.makeText(这一点,新形象保存:+ photoFile,
              Toast.LENGTH_LONG).show();

        }赶上(异常错误){
            Log.d(文件不保存,error.getMessage());
          Toast.makeText(这一点,图像无法被保存。
              Toast.LENGTH_LONG).show();
        }
        反++;
      }



    私人诠释findFrontFacingCamera(){
        INT cameraId = -1;
        //搜索的前置摄像头
        INT numberOfCameras = Camera.getNumberOfCameras();
        的for(int i = 0; I< numberOfCameras;我++){
            CameraInfo信息=新CameraInfo();
            Camera.getCameraInfo(ⅰ,信息);
            如果(info.facing == CameraInfo.CAMERA_FACING_BACK){
                Log.d(ClassScanViewBar codeActivity,findFrontFacingCamera(),
                        相机找到);
                cameraId =我;
                打破;
            }
        }
        返回cameraId;
    } //结束findFrontFacingCamera()

    @覆盖
    保护无效的onPause(){
        如果(globalCamera!= NULL){
            globalCamera.stop preVIEW();
            globalCamera.set previewCallback(空);
            globalCamera.release();
            globalCamera = NULL;
        }
        super.onPause();
    } //结束的onPause()

    公共字符串德codeBitmapToString(BinaryBitmap位){
        读卡器读卡器= NULL;
        结果结果= NULL;
        字符串textResult = NULL;
        尝试 {

            读者=新MultiFormatReader();
            如果(位图!= NULL){
                结果= reader.de code(位);
                如果(结果!= NULL){
                    textResult = result.getText();
                } 其他 {
                    Log.d(ClassScanViewBar codeActivity,串去codeBitmapToString(BinaryBitmap位):结果=,
                            将String.valueOf(结果));
                }
            } 其他 {
                Log.d(ClassScanViewBar codeActivity,串去codeBitmapToString(BinaryBitmap位):位图=
                        将String.valueOf(位图));
            }
            / *
             * byte []的rawBytes = result.getRawBytes();酒吧codeFormat格式=
             * result.getBar codeFormat(); ResultPoint []点=
             * result.getResultPoints();
             * /

        }赶上(NotFoundException E){
            // TODO自动生成的catch块
            e.printStackTrace();
        }赶上(ChecksumException E){
            // TODO自动生成的catch块
            e.printStackTrace();
        }赶上(出现FormatException E){
            // TODO自动生成的catch块
            e.printStackTrace();

        }

        返回textResult;
    } //结束日codeBitmapToString(BinaryBitmap位图)

    公共BinaryBitmap cameraBytesToBinaryBitmap(位图位图){
        BinaryBitmap binaryBitmap = NULL;
        如果(位图!= NULL){

            INT []个像素=新INT [bitmap.getHeight()* bitmap.getWidth()];
            bitmap.getPixels(像素,0,0,bitmap.getWidth() -  1,
                    bitmap.getHeight() -  1,bitmap.getWidth(),
                    bitmap.getHeight());

            RGBLuminanceSource源=新RGBLuminanceSource(
                    bitmap.getWidth(),bitmap.getHeight(),像素);

            HybridBinarizer BH =新HybridBinarizer(源);
            binaryBitmap =新BinaryBitmap(BH);
        } 其他 {
            Log.d(ClassScanViewBar codeActivity,cameraBytesToBinaryBitmap(位图位):位图=
                    将String.valueOf(位图));
        }

        返回binaryBitmap;
    }

    @燮pressLint(NewApi)
    @燮pressWarnings(德precation)
    / *
     *该方法getScreenOrientation()返回屏幕方向无论是
     *横向或纵向。如果width<高度,比方向=纵向,
     * ELSE景观为了向后兼容,我们使用的方法来检测
     *的方向。第一种方法之前,图13是用于API的版本或
     * 蜂窝。
     * /
    公众诠释getScreenOrientation(){

        INT currentapiVersion = android.os.Build.VERSION.SDK_INT;
        //如果API版本小于13
        显示getOrient = getWindowManager()getDefaultDisplay()。
        INT方向= Configuration.ORIENTATION_UNDEFINED;

        如果(currentapiVersion< android.os.Build.VERSION_ codeS.HONEYCOMB){
            //做一些对API版本低于蜂窝

            如果(getOrient.getWidth()== getOrient.getHeight()){
                定向= Configuration.ORIENTATION_SQUARE;
            } 其他 {
                如果(getOrient.getWidth()&其中; getOrient.getHeight()){
                    定向= Configuration.ORIENTATION_PORTRAIT;
                } 其他 {
                    定向= Configuration.ORIENTATION_LANDSCAPE;
                }
            }
        } 其他 {
            //做一些对API版本大于或等于蜂窝

            点大小=新的点();
            。this.getWindowManager()getDefaultDisplay()的getSize(大小)。
            INT宽度= size.x;
            INT高= size.y;

            如果(宽度LT;高度){
                定向= Configuration.ORIENTATION_PORTRAIT;
            } 其他 {
                定向= Configuration.ORIENTATION_LANDSCAPE;
            }
        }

        返回的方向;

    } //结束getScreenOrientation()
} //结束类ScanVinFromBar codeActivity
 

用于在SurfaceView(相机preview.java)显示现场摄像机的 preVIEW类:

 包com.ty.tyownerspoc.bar code;

进口java.io.IOException异常;
进口的java.util.List;

进口android.content.Context;
进口android.hardware.Camera;
进口android.hardware.Camera.Size;
进口android.util.Log;
进口android.view.SurfaceHolder;
进口android.view.SurfaceView;
进口android.view.ViewGroup;
进口android.hardware.Camera.CameraInfo;

/ **基本型摄像机preVIEW类* /
公共类相机preVIEW延伸SurfaceView工具
        SurfaceHolder.Callback {
    私人SurfaceHolder mHolder;
    私人相机mCamera;
    私人上下文的背景下;

    公共摄像头preVIEW(上下文的背景下,相机摄像头){
        超(上下文);
        mCamera =摄像头;
        this.context =背景;

        //安装SurfaceHolder.Callback所以我们得到通知时,该
        //下垫面创建和销毁。
        mHolder = getHolder();
        mHolder.addCallback(本);
        //德precated设置,但在Android上之前的版本3.0所需
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    公共无效surfaceCreated(SurfaceHolder持有者){
        //表面有被创建,现在告诉相机在哪里画的
        // preVIEW。
        尝试 {
            mCamera.set previewDisplay(保持器);
            mCamera.start preVIEW();
        }赶上(IOException异常E){

        }
    }

    公共无效surfaceDestroyed(SurfaceHolder持有者){
        //空。以释放相机preVIEW在您的活动的照顾。
    }

    公共无效surfaceChanged(SurfaceHolder持有人,INT格式,INT W,INT高){
        //如果你的preVIEW可以改变或旋转,把这些事件的关心在这里。
        //确保调整或重新格式化之前停止preVIEW。

        如果(mHolder.getSurface()== NULL){
            // preVIEW表面不存在
            返回;
        }

        在进行更改之前//停止preVIEW
        尝试 {
            mCamera.stop preVIEW();
        }赶上(例外五){
            //忽略:试图阻止一个不存在的preVIEW
        }
                Camera.Parameters p值= mCamera.getParameters();

        //获取宽度和放大器;在SurfaceView的高度
        INT SurfaceViewWidth = this.getWidth();
        INT SurfaceViewHeight = this.getHeight();

        名单<大小>大小= p.getSupported previewSizes();
         大小optimalSize = getOptimal previewSize(尺寸,SurfaceViewWidth,SurfaceViewHeight);


        //设置参数
        P.SET previewSize(optimalSize.width,optimalSize.height);

        / *将图像旋转90度顺时针,为了正确地显示的图像,图像似乎是-90度(逆时针)旋转
         *我甚至试图将其设置为p.setRotation(0); ,但仍然没有效果。
         * /
        mCamera.setDisplayOrientation(90);

        mCamera.setParameters(对);

        //启动preVIEW使用新设置
        尝试 {
            mCamera.set previewDisplay(mHolder);
            mCamera.start preVIEW();

        }赶上(例外五){
            Log.d(摄像机preVIEW,surfaceCreated(),方向:,
                    将String.valueOf(e.getMessage()));
        }
    } //结束surfaceChanged()
     静态尺寸getOptimal previewSize(名单< Camera.Size>的大小,INT W,INT高){
            最终双ASPECT_TOLERANCE = 0.1;
            最终双MAX_DOWNSIZE = 1.5;

            双targetRatio =(双)W / H;
            如果(大小== NULL)返回NULL;

            大小optimalSize = NULL;
            双minDiff = Double.MAX_VALUE;

            INT targetHeight = H;

            //试着找一个大小匹配纵横比和尺寸
            对于(Camera.Size大小:大小){
              双率=(双)size.width / size.height;
              双裁员=(双)size.width / W;
              如果(缩小> MAX_DOWNSIZE){
                //如果preVIEW比我们的展示面大了很多忽略它
                //原因 - 在某些手机上没有足够的堆可用来显示较大的preVIEW尺寸
                继续;
              }
              如果(Math.abs(比 -  targetRatio)> ASPECT_TOLERANCE)继续;
              如果(Math.abs(size.height  -  targetHeight)< minDiff){
                optimalSize =大小;
                minDiff = Math.abs(size.height  -  targetHeight);
              }
            }
            //不能找到一个匹配的纵横比,忽略此要求
            //保持max_downsize要求
            如果(optimalSize == NULL){
              minDiff = Double.MAX_VALUE;
              对于(尺寸大小:大小){
                双裁员=(双)size.width / W;
                如果(缩小> MAX_DOWNSIZE){
                  继续;
                }
                如果(Math.abs(size.height  -  targetHeight)< minDiff){
                  optimalSize =大小;
                  minDiff = Math.abs(size.height  -  targetHeight);
                }
              }
            }
            //一切失败,只取最接近的匹配
            如果(optimalSize == NULL){
              minDiff = Double.MAX_VALUE;
              对于(尺寸大小:大小){
                如果(Math.abs(size.height  -  targetHeight)< minDiff){
                  optimalSize =大小;
                  minDiff = Math.abs(size.height  -  targetHeight);
                }
              }
            }
            返回optimalSize;
          }

} //结束preVIEW类
 

布局为ScanVinFromBar codeActivity活动(activity_bar code_vin_scanner.xml):

 < XML版本=1.0编码=UTF-8&GT?;
< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =FILL_PARENT
    机器人:layout_height =FILL_PARENT
    机器人:方向=垂直
    机器人:填充=20dip>

    <的TextView
        机器人:layout_width =FILL_PARENT
        机器人:layout_height =WRAP_CONTENT
        机器人:重力=center_horizo​​ntal
        机器人:填充=20dip
        机器人:文本=@字符串/日code_label
        机器人:文字颜色=@色/ mbackground1/>

    <的TextView
        机器人:ID =@ + ID / MYTEXT
        机器人:layout_width =WRAP_CONTENT
        机器人:layout_height =WRAP_CONTENT
        机器人:背景=@色/ mbackground2
        机器人:重力=center_horizo​​ntal
        机器人:填充=20dip
        机器人:文字颜色=@色/ mytextcolor/>

    <的TextView
        机器人:layout_width =FILL_PARENT
        机器人:layout_height =WRAP_CONTENT
        机器人:重力=center_horizo​​ntal
        机器人:填充=20dip
        机器人:文本=@字符串/ continue_label
        机器人:文字颜色=@色/ mytextcolor/>

    <按钮
        机器人:ID =@ + ID / webbutton
        机器人:layout_width =FILL_PARENT
        机器人:layout_height =WRAP_CONTENT
        机器人:文本=@字符串/ web_button
        机器人:文字颜色=@色/ mytextcolor/>

    <的FrameLayout
    机器人:ID =@ + ID / FrameLayoutFor preVIEW
    机器人:layout_width =FILL_PARENT
    机器人:layout_height =FILL_PARENT
    机器人:layout_weight =1>

        < SurfaceView
            机器人:ID =@ + ID / surfaceViewBar codeScanner
            机器人:layout_width =WRAP_CONTENT
            机器人:layout_height =WRAP_CONTENT/>

    < /的FrameLayout>
< / LinearLayout中>
 
android byte转string 从OWASP CrackMe学Android逆向 一

任何帮助将AP preciated。

感谢

 更新和放大器;工作onTakePicturen法,这样的作品,在PictureCallback回报(停止preVIEW和放大器;启动preVIEW是在其最后的块移动到该方法内)。


    公共无效onPictureTaken(byte []的imgData,相机摄像头){
        BinaryBitmap位图;
        尝试 {



            Log.d(ClassScanViewBar codeActivity,onPictureTaken());

            //保存图片到SD卡
            savePicture(imgData);

            //从相机为imageData位图

            BitmapFactory.Options选项=新BitmapFactory.Options();
              options.inSampleSize = 8;
              //下采样
            bmpOfTheImageFromCamera = BitmapFactory.de codeByteArray(
                    imgData,0,imgData.length,期权);


            如果(bmpOfTheImageFromCamera!= NULL){

                Log.d(*** ClassScanViewBar codeActivity,onPictureTaken():bmpOfTheImageFromCamera getByteCount(),
                        将String.valueOf(bmpOfTheImageFromCamera.getByteCount()));
                //银河S3,不正确的轮换问题旋转到正确的旋转
                / *矩阵的矩阵=新的Matrix();
                matrix.postRotate(90);
                位图rotatedBitmap = Bitmap.createBitmap(bmpOfTheImageFromCamera,0,0,bmpOfTheImageFromCamera.getWidth(),bmpOfTheImageFromCamera.getHeight(),矩阵,真); * /
                //位图转换成二进制位图
                位= cameraBytesToBinaryBitmap(bmpOfTheImageFromCamera);


                如果(位图!= NULL){
                    //德$ C C的VIN $
                    字符串VIN =去codeBitmapToString(位);
                    Log.d(*** ClassScanViewBar codeActivity,onPictureTaken():VIN,
                            VIN);
                    VINtext.setText(VIN);
                } 其他 {
                    Log.d(ClassScanViewBar codeActivity,onPictureTaken():位图=,将String.valueOf(位图));

                }
            } 其他 {
                Log.d(ClassScanViewBar codeActivity,onPictureTaken():bmpOfTheImageFromCamera =,
                        将String.valueOf(bmpOfTheImageFromCamera));

            }


        } //结束试

        赶上(例外EXC){
            exc.getMessage();

            Log.d(ClassScanViewBar codeActivity,scanButton.setOnClickListener():异常=,
                    exc.getMessage());
        }

        最后
        {
            globalCamera.stop preVIEW();
            //再次启动previewing onthe SurfaceView的情况下使用要采取另一种PIC /扫描
            globalCamera.start preVIEW();
        }

    } //结束onPictureTaken()
}; // jpegCallback实施
 

解决方案

我唯一能找到的可能是罪魁祸首就是你再次启动preVIEW前 jpegCallback 返回。根据javadoc,这是不允许的:

  

调用此方法后,你不能调用start preVIEW()或拍摄另一张照片,直到JPEG回调又回来了。

回调实际上是放在UI线程队列 - 这将在你的视频下载()和相同的线程将有一个名为停止preVIEW()和其实之前来回调开始preVIEW()。一般来说,如果你调用视频下载()在UI线程 - 你就错了。所以,我希望,如果你删除睡眠()和放什么来后它在 jpegCallback 你的问题应该得到解决。

I have a custom camera app , that previews the camera video output on SurfaceView and attempts to take pictures , the pics should be will be processed by "xzing "scanner API to decode any barcodes in the image.

My app previews correctly and does not throw any errors or expectations, however my onPictureTaken(byte[] imgData, Camera camera) method & PictureCallback are never called, therefore I’m unable to get the image & continue with further scanning.

Below is the actual code for activity that takes care of Camera logic. The onPictureTaken(byte[] imgData, Camera camera) method & PictureCallback are in this class(ScanVinFromBarcodeActivity.java) see blow :

package com.ty.tyownerspoc.barcode;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.FormatException;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource; 
import com.google.zxing.Reader;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Point;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.ty.tyownerspoc.R;

public class ScanVinFromBarcodeActivity extends Activity {

    private Camera globalCamera;
    private int cameraId = 0;
    private TextView VINtext = null;
    private View scanButton = null;
    // bitmap from camera
    private Bitmap bmpOfTheImageFromCamera = null;
    // global flag whether a camera has been detected
    private boolean isThereACamera = false;
    // surfaceView for preview object
    private FrameLayout frameLayoutBarcodeScanner = null;
    private CameraPreview newCameraPreview = null;
    private SurfaceView surfaceViewBarcodeScanner = null;
    private int counter = 0; 
    private volatile boolean finishedPictureTask  = false;
    /*
     * This method , finds FEATURE_CAMERA, opens the camera, set parameters ,
     * add CameraPreview to layout, set camera surface holder, start preview
     */
    private void initializeGlobalCamera() {
        try {
            if (!getPackageManager().hasSystemFeature(
                    PackageManager.FEATURE_CAMERA)) {
                Toast.makeText(this, "No camera on this device",
                        Toast.LENGTH_LONG).show();
            } else { // check for front camera ,and get the ID
                cameraId = findFrontFacingCamera();
                if (cameraId < 0) {

                    Toast.makeText(this, "No front facing camera found.",
                            Toast.LENGTH_LONG).show();
                } else {

                    Log.d("ClassScanViewBarcodeActivity",
                            "camera was found , ID: " + cameraId);
                    // camera was found , set global camera flag to true
                    isThereACamera = true;
                    // OPEN
                    globalCamera = Camera.open(cameraId);

                    // pass surfaceView to CameraPreview
                    newCameraPreview = new CameraPreview(this, globalCamera);
                    // pass CameraPreview to Layout
                    frameLayoutBarcodeScanner.addView(newCameraPreview);
                    try {
                        globalCamera
                                .setPreviewDisplay(surfaceViewBarcodeScanner
                                        .getHolder());
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    // PREVIEW
                    globalCamera.startPreview();

                    Log.d("ClassScanViewBarcodeActivity",
                            "camera opened & previewing");
                }
            }// end else ,check for front camera
        }// end try
        catch (Exception exc) {

            // in case of exception release resources & cleanup
            if (globalCamera != null) {
                globalCamera.stopPreview();
                globalCamera.setPreviewCallback(null);
                globalCamera.release();
                globalCamera = null;

            }
            Log.d("ClassScanViewBarcodeActivity initializeGlobalCamera() exception:",
                    exc.getMessage());
        }// end catch
    }

    // onCreate, instantiates layouts & surfaceView used for video preview
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_barcode_vin_scanner);
        Log.d("ClassScanViewBarcodeActivity", "onCreate ");

        // create surfaceView for previewing of camera image
        frameLayoutBarcodeScanner = (FrameLayout) findViewById(R.id.FrameLayoutForPreview);
        surfaceViewBarcodeScanner = (SurfaceView) findViewById(R.id.surfaceViewBarcodeScanner);

        initializeGlobalCamera();

        // create text area & scan button
        VINtext = (TextView) findViewById(R.id.mytext);
        scanButton = findViewById(R.id.webbutton);
        // on click listener, onClick take a picture
        scanButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {

                    // if true take a picture
                    if (isThereACamera) {
                        Log.d("ClassScanViewBarcodeActivity",
                                "setOnClickListener() isThereACamera: "+ isThereACamera);

                        //set picture format to JPEG, everytime makesure JPEg callback is called 
                         Parameters parameters = globalCamera.getParameters();              
                         parameters.setPictureFormat(ImageFormat.JPEG);
                         globalCamera.setParameters(parameters);                         
                         //take pic , should call Callback 
                        globalCamera.takePicture(null, null, jpegCallback);
                        // wait 1 sec , than start preview again
                        Thread.sleep(1000);
                        //STOP
                        globalCamera.stopPreview();
                        //start previewing again onthe SurfaceView in case use wants to take another pic/scan
                        globalCamera.startPreview();

                    }

                }// end try
                catch (Exception exc) {

                    // in case of exception release resources & cleanup
                    if (globalCamera != null) {
                        globalCamera.stopPreview();
                        globalCamera.setPreviewCallback(null);
                        globalCamera.release();
                        globalCamera = null;

                    }
                    Log.d("ClassScanViewBarcodeActivity setOnClickListener() exceprtion:",
                            exc.getMessage());
                }// end catch

            }// end on Click
        });// end OnClickListener() implementation

    }// end onCreate

    @Override
    protected void onResume() {

        Log.d("ClassScanViewBarcodeActivity, onResume() globalCamera:",
                String.valueOf(globalCamera));

        if (globalCamera != null) {
            // START PREVIEW
            globalCamera.startPreview();
        } else {
            initializeGlobalCamera();
        }

        super.onResume();
    }

    @Override
    protected void onStop() {

        if (globalCamera != null) {
            globalCamera.stopPreview();
            globalCamera.setPreviewCallback(null);
            globalCamera.release();
            globalCamera = null;
        }
        super.onStop();
    }

    //callback used by takePicture()
    PictureCallback jpegCallback = new PictureCallback() {



        public void onPictureTaken(byte[] imgData, Camera camera) {
            BinaryBitmap bitmap = null;
            try {



                Log.d("ClassScanViewBarcodeActivity" ,"onPictureTaken()");

                //save image to sd card 
                savePicture(imgData);

                // get the bitmap from camera imageData
                bmpOfTheImageFromCamera = BitmapFactory.decodeByteArray(
                        imgData, 0, imgData.length);


                if (bmpOfTheImageFromCamera != null) {
                    //Galaxy S3 , incorrect rotation issue rotate to correct rotation
                    Matrix matrix = new Matrix();
                    matrix.postRotate(90);
                    Bitmap rotatedBitmap = Bitmap.createBitmap(bmpOfTheImageFromCamera, 0, 0, bmpOfTheImageFromCamera.getWidth(), bmpOfTheImageFromCamera.getHeight(), matrix, true);
                    // convert bitmap to binary bitmap
                    bitmap = cameraBytesToBinaryBitmap(rotatedBitmap);


                    if (bitmap != null) {
                        // decode the VIN
                        String VIN = decodeBitmapToString(bitmap);
                        Log.d("***ClassScanViewBarcodeActivity ,onPictureTaken(): VIN ",
                                VIN);
                        VINtext.setText(VIN);
                    } else {
                        Log.d("ClassScanViewBarcodeActivity ,onPictureTaken(): bitmap=",String.valueOf(bitmap));

                    }
                } else {
                    Log.d("ClassScanViewBarcodeActivity , onPictureTaken(): bmpOfTheImageFromCamera = ",
                            String.valueOf(bmpOfTheImageFromCamera));

                }
            }// end try

            catch (Exception exc) {
                exc.getMessage();

                Log.d("ClassScanViewBarcodeActivity , scanButton.setOnClickListener(): exception = ",
                        exc.getMessage());
            }

        }// end onPictureTaken()
    };// jpegCallback implementation


    /*
     * created savePicture(byte [] data) for testing 
     */
    public void savePicture(byte [] data)
    {
        Log.d( "ScanVinFromBarcodeActivity " , "savePicture(byte [] data)");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
        String date = dateFormat.format(new Date());
        String photoFile = "Picture_"+counter+"_"+ date + ".jpg";

        File sdDir = Environment
                  .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);


        String filename =sdDir + File.separator + photoFile;

        File pictureFile = new File(filename);

        try {
          FileOutputStream fos = new FileOutputStream(pictureFile);
          fos.write(data);
          fos.close();

          Toast.makeText(this, "New Image saved:" + photoFile,
              Toast.LENGTH_LONG).show();

        } catch (Exception error) {
            Log.d( "File not saved: " , error.getMessage());
          Toast.makeText(this, "Image could not be saved.",
              Toast.LENGTH_LONG).show();
        }
        counter++;
      }



    private int findFrontFacingCamera() {
        int cameraId = -1;
        // Search for the front facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            CameraInfo info = new CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
                Log.d("ClassScanViewBarcodeActivity , findFrontFacingCamera(): ",
                        "Camera found");
                cameraId = i;
                break;
            }
        }
        return cameraId;
    }// end findFrontFacingCamera()

    @Override
    protected void onPause() {
        if (globalCamera != null) {
            globalCamera.stopPreview();
            globalCamera.setPreviewCallback(null);
            globalCamera.release();
            globalCamera = null;
        }
        super.onPause();
    }// end onPause()

    public String decodeBitmapToString(BinaryBitmap bitmap) {
        Reader reader = null;
        Result result = null;
        String textResult = null;
        try {

            reader = new MultiFormatReader();
            if (bitmap != null) {
                result = reader.decode(bitmap);
                if (result != null) {
                    textResult = result.getText();
                } else {
                    Log.d("ClassScanViewBarcodeActivity , String decodeBitmapToString (BinaryBitmap bitmap): result = ",
                            String.valueOf(result));
                }
            } else {
                Log.d("ClassScanViewBarcodeActivity , String decodeBitmapToString (BinaryBitmap bitmap): bitmap = ",
                        String.valueOf(bitmap));
            }
            /*
             * byte[] rawBytes = result.getRawBytes(); BarcodeFormat format =
             * result.getBarcodeFormat(); ResultPoint[] points =
             * result.getResultPoints();
             */

        } catch (NotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ChecksumException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (FormatException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        }

        return textResult;
    }// end decodeBitmapToString (BinaryBitmap bitmap)

    public BinaryBitmap cameraBytesToBinaryBitmap(Bitmap bitmap) {
        BinaryBitmap binaryBitmap = null;
        if (bitmap != null) {

            int[] pixels = new int[bitmap.getHeight() * bitmap.getWidth()];
            bitmap.getPixels(pixels, 0, 0, bitmap.getWidth() - 1,
                    bitmap.getHeight() - 1, bitmap.getWidth(),
                    bitmap.getHeight());

            RGBLuminanceSource source = new RGBLuminanceSource(
                    bitmap.getWidth(), bitmap.getHeight(), pixels);

            HybridBinarizer bh = new HybridBinarizer(source);
            binaryBitmap = new BinaryBitmap(bh);
        } else {
            Log.d("ClassScanViewBarcodeActivity , cameraBytesToBinaryBitmap (Bitmap bitmap): bitmap = ",
                    String.valueOf(bitmap));
        }

        return binaryBitmap;
    }

    @SuppressLint("NewApi")
    @SuppressWarnings("deprecation")
    /*
     * The method getScreenOrientation() return screen orientation either
     * landscape or portrait. IF width < height , than orientation = portrait,
     * ELSE landscape For backwards compatibility we use to methods to detect
     * the orientation. The first method is for API versions prior to 13 or
     * HONEYCOMB.
     */
    public int getScreenOrientation() {

        int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        // if API version less than 13
        Display getOrient = getWindowManager().getDefaultDisplay();
        int orientation = Configuration.ORIENTATION_UNDEFINED;

        if (currentapiVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
            // Do something for API version less than HONEYCOMB

            if (getOrient.getWidth() == getOrient.getHeight()) {
                orientation = Configuration.ORIENTATION_SQUARE;
            } else {
                if (getOrient.getWidth() < getOrient.getHeight()) {
                    orientation = Configuration.ORIENTATION_PORTRAIT;
                } else {
                    orientation = Configuration.ORIENTATION_LANDSCAPE;
                }
            }
        } else {
            // Do something for API version greater or equal to HONEYCOMB

            Point size = new Point();
            this.getWindowManager().getDefaultDisplay().getSize(size);
            int width = size.x;
            int height = size.y;

            if (width < height) {
                orientation = Configuration.ORIENTATION_PORTRAIT;
            } else {
                orientation = Configuration.ORIENTATION_LANDSCAPE;
            }
        }

        return orientation;

    }// end getScreenOrientation()
}// end class ScanVinFromBarcodeActivity

Preview class used to display live camera on SurfaceView (CameraPreview.java):

package com.ty.tyownerspoc.barcode;

import java.io.IOException;
import java.util.List;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.hardware.Camera.CameraInfo;

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements
        SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private Context context;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        this.context = context;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the
        // preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {

        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null) {
            // preview surface does not exist
            return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            // ignore: tried to stop a non-existent preview
        }
                Camera.Parameters p = mCamera.getParameters();

        // get width & height of the SurfaceView
        int SurfaceViewWidth = this.getWidth();
        int SurfaceViewHeight = this.getHeight();

        List<Size> sizes = p.getSupportedPreviewSizes();
         Size optimalSize = getOptimalPreviewSize(sizes, SurfaceViewWidth, SurfaceViewHeight);


        // set parameters
        p.setPreviewSize(optimalSize.width, optimalSize.height);

        /*rotate the image by 90 degrees clockwise , in order to correctly displayed the image , images seem to be -90 degrees (counter clockwise) rotated 
         * I even tried setting it to  p.setRotation(0); , but still no effect.
         */
        mCamera.setDisplayOrientation(90);

        mCamera.setParameters(p);

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e) {
            Log.d("CameraPreview ,  surfaceCreated() , orientation: ",
                    String.valueOf(e.getMessage()));
        }
    }// end surfaceChanged()
     static Size getOptimalPreviewSize(List <Camera.Size>sizes, int w, int h) {
            final double ASPECT_TOLERANCE = 0.1;
            final double MAX_DOWNSIZE = 1.5;

            double targetRatio = (double) w / h;
            if (sizes == null) return null;

            Size optimalSize = null;
            double minDiff = Double.MAX_VALUE;

            int targetHeight = h;

            // Try to find an size match aspect ratio and size
            for (Camera.Size size : sizes) {
              double ratio = (double) size.width / size.height;
              double downsize = (double) size.width / w;
              if (downsize > MAX_DOWNSIZE) {
                //if the preview is a lot larger than our display surface ignore it
                //reason - on some phones there is not enough heap available to show the larger preview sizes
                continue;
              }
              if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
              if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
              }
            }
            // Cannot find the one match the aspect ratio, ignore the requirement
            //keep the max_downsize requirement
            if (optimalSize == null) {
              minDiff = Double.MAX_VALUE;
              for (Size size : sizes) {
                double downsize = (double) size.width / w;
                if (downsize > MAX_DOWNSIZE) {
                  continue;
                }
                if (Math.abs(size.height - targetHeight) < minDiff) {
                  optimalSize = size;
                  minDiff = Math.abs(size.height - targetHeight);
                }
              }
            }
            //everything else failed, just take the closest match
            if (optimalSize == null) {
              minDiff = Double.MAX_VALUE;
              for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                  optimalSize = size;
                  minDiff = Math.abs(size.height - targetHeight);
                }
              }
            }
            return optimalSize;
          }

}//end Preview class

Layout for the "ScanVinFromBarcodeActivity" activity (activity_barcode_vin_scanner.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:padding="20dip" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:padding="20dip"
        android:text="@string/decode_label"
        android:textColor="@color/mbackground1" />

    <TextView
        android:id="@+id/mytext"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/mbackground2"
        android:gravity="center_horizontal"
        android:padding="20dip"
        android:textColor="@color/mytextcolor" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:padding="20dip"
        android:text="@string/continue_label"
        android:textColor="@color/mytextcolor" />

    <Button
        android:id="@+id/webbutton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/web_button"
        android:textColor="@color/mytextcolor" />

    <FrameLayout
    android:id="@+id/FrameLayoutForPreview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1">

        <SurfaceView
            android:id="@+id/surfaceViewBarcodeScanner"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </FrameLayout>
</LinearLayout>

Any help will be appreciated.

Thanks

Updated & working onTakePicturen method, the that works , the PictureCallback returns (stopPreview & StartPreview were moved to inside this method in its finally block).


    public void onPictureTaken(byte[] imgData, Camera camera) {
        BinaryBitmap bitmap;
        try {



            Log.d("ClassScanViewBarcodeActivity" ,"onPictureTaken()");

            //save image to sd card 
            savePicture(imgData);

            // get the bitmap from camera imageData

            BitmapFactory.Options options = new BitmapFactory.Options();
              options.inSampleSize = 8; 
              //down sample
            bmpOfTheImageFromCamera = BitmapFactory.decodeByteArray(
                    imgData, 0, imgData.length,options);


            if (bmpOfTheImageFromCamera != null) {

                Log.d("***ClassScanViewBarcodeActivity ,onPictureTaken(): bmpOfTheImageFromCamera getByteCount(): ",
                        String.valueOf(bmpOfTheImageFromCamera.getByteCount()));
                //Galaxy S3 , incorrect rotation issue rotate to correct rotation
                /*Matrix matrix = new Matrix();
                matrix.postRotate(90);
                Bitmap rotatedBitmap = Bitmap.createBitmap(bmpOfTheImageFromCamera, 0, 0, bmpOfTheImageFromCamera.getWidth(), bmpOfTheImageFromCamera.getHeight(), matrix, true);*/
                // convert bitmap to binary bitmap
                bitmap = cameraBytesToBinaryBitmap(bmpOfTheImageFromCamera);


                if (bitmap != null) {
                    // decode the VIN
                    String VIN = decodeBitmapToString(bitmap);
                    Log.d("***ClassScanViewBarcodeActivity ,onPictureTaken(): VIN ",
                            VIN);
                    VINtext.setText(VIN);
                } else {
                    Log.d("ClassScanViewBarcodeActivity ,onPictureTaken(): bitmap=",String.valueOf(bitmap));

                }
            } else {
                Log.d("ClassScanViewBarcodeActivity , onPictureTaken(): bmpOfTheImageFromCamera = ",
                        String.valueOf(bmpOfTheImageFromCamera));

            }


        }// end try

        catch (Exception exc) {
            exc.getMessage();

            Log.d("ClassScanViewBarcodeActivity , scanButton.setOnClickListener(): exception = ",
                    exc.getMessage());
        }

        finally
        {
            globalCamera.stopPreview();
            //start previewing again onthe SurfaceView in case use wants to take another pic/scan
            globalCamera.startPreview();
        }

    }// end onPictureTaken()
};// jpegCallback implementation

解决方案

The only thing I can find that might be the culprit is that you're starting the preview again before the jpegCallback has returned. According to the javadoc, this is not allowed:

After calling this method, you must not call startPreview() or take another picture until the JPEG callback has returned.

The callback is actually put on the UI thread queue - which will be suspended in your Thread.sleep() and the same thread will have called stopPreview() and startPreview() before actually coming to the callback. Generally speaking, if you call Thread.sleep() on the UI thread - you're doing it wrong. So, hopefully if you remove the sleep() and put what comes after it in the jpegCallback your problem should be solved.