需要帮助修复“java.lang.RuntimeException:takePicture failed”

时间:2015-10-16 01:23:37

标签: android android-activity android-camera

我必须创建一个在后台捕获图片的android应用程序。我有代码,但它总是在某一时刻崩溃。这段代码在HTC android手机上运行良好。我在摩托罗拉,nexus及其崩溃时都尝试过它。

这是崩溃:

Process: com.capturepicture, PID: 13016
    java.lang.RuntimeException: takePicture failed
            at android.hardware.Camera.native_takePicture(Native Method)
            at android.hardware.Camera.takePicture(Camera.java:1436)
            at android.hardware.Camera.takePicture(Camera.java:1381)
            at com.trimble.applanix.flightplanning.FlightPlanner.takepic(FlightPlanner.java:142)
            at com.trimble.applanix.flightplanning.FlightPlanner$2.onClick(FlightPlanner.java:96)
            at android.view.View.performClick(View.java:4761)
            at android.view.View$PerformClick.run(View.java:19767)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5312)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)

这是我的活动文件,它触发了摄像头代码

public class Planner extends Activity {

    private Button btnStart;
    private Button btnStop;
    protected static Handler mHandler = null;
    protected String mHttpResponse = "";
    private int mHandlerWhatMessage;
    Camera camera;
    SurfaceView preview;
    SurfaceHolder previewHolder;
    ImageButton takePic;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flight_planner);

        btnStart = (Button) findViewById(R.id.btn_start);
        btnStop = (Button) findViewById(R.id.btn_stop);
        preview = (SurfaceView) findViewById(R.id.surfaceView);
        previewHolder = preview.getHolder();
        previewHolder.addCallback(surfaceCallback);
        previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);


        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                takepic();



            }
        });

        btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {


            }
        });

    }


    public void takepic(){
        if (camera == null)
            camera = Camera.open();
        camera.cancelAutoFocus();
        camera.startPreview();

        System.gc();
        camera.setPreviewCallback(null);
        camera.takePicture(null, null, photoCallback);
        camera.startPreview();
        //camera.takePicture(ShutterCallback, rawCallback, photoCallback);
    }
    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);
    }

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

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            camera = Camera.open();

            try {
                camera.setPreviewDisplay(previewHolder);
            } catch (Throwable t) {
                Toast toast = Toast.makeText(FlightPlanner.this,
                        "Exception in setPreviewDisplay", Toast.LENGTH_LONG);
                toast.show();
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                                   int height) {
            Camera.Parameters parameters = camera.getParameters();

            Camera.Size bestSize = getBestPreviewSize(width, height, parameters);
            parameters.setPreviewSize(bestSize.width, bestSize.height);

            parameters.setPictureFormat(PixelFormat.JPEG);
            camera.setParameters(parameters);
            camera.startPreview();
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            camera.stopPreview();
            camera.release();
            camera = null;
        }

    };

        /*
        Camera.ShutterCallback ShutterCallback = new Camera.ShutterCallback() {
            public void onShutter() {
            }
        };

        PictureCallback rawCallback = new PictureCallback() {
            public void onPictureTaken(byte[] data, Camera camera) {
            }
        };
        */

    Camera.PictureCallback photoCallback = new Camera.PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {
            // Save the image JPEG data to the SD card
            FileOutputStream outStream = null;
            try {

                SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
                Date now = new Date();
                String fileName = formatter.format(now) +".jpg";
                //String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());
                String root = Environment.getExternalStorageDirectory().toString();
                File myDir = new File(root + "/FLIGHTPLANNER");
                myDir.mkdirs();
                File file = new File (myDir, fileName);
                if (file.exists ()) file.delete ();

                outStream = new FileOutputStream(file);
                outStream.write(data);
                outStream.close();
            } catch (FileNotFoundException e) {
                Log.d("CAMERA", e.getMessage());
            } catch (IOException e) {
                Log.d("CAMERA", e.getMessage());
            }
            camera.startPreview();
                /*new SavePhotoTask().execute(data);
                camera.startPreview();*/
        }
    };
}

我在清单文件中添加了必需的相机权限。

1 个答案:

答案 0 :(得分:1)

您必须先调用startPreview(),然后才能调用takePicture()。但是在调用startPreview()之后立即调用takePicture()是不正确的。它可能适用于某些设备,但不适用于其他设备。

一旦打开相机(当布局管理器创建SurfaceView时),最佳解决方案将开始预览。

但如果你不能接受,

preview.postDelayed(…, 300)

就足够了(参见类似的例子on GitHub