13

The error occurs inside CameraFragment - a fragment containing just a FrameLayout (to hold the camera preview) and ImageButton (used to capture the image). In my Fragment I have a PictureCallback:

private static Camera.PictureCallback mPicture = new Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        CameraFragment.DATA=data;
        final int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    activity,
                    PERMISSIONS_STORAGE,
                    REQUEST_STORAGE
            );
            return;
        }
        saveImageToDevice();

    }
};

and I get my Camera instance from a HandlerThread:

private CameraHandlerThread mThread = null;

private static class CameraHandlerThread extends HandlerThread {
    Handler mHandler = null;
    private Camera handlerCamera;

    CameraHandlerThread() {
        super("CameraHandlerThread");
        start();
        mHandler = new Handler(getLooper());
    }

    synchronized void notifyCameraOpened() {
        notify();
    }

    void openCamera() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                handlerCamera = getCameraInstance();
                notifyCameraOpened();
            }
        });
        try {
            wait();
        }
        catch (InterruptedException e) {

        }
    }

    public Camera getCamera() {
        return handlerCamera;
    }
}

then I call this method (where the exception occurs) in OnCreateView():

private void launchCamera() {
    newOpenCamera();
    mPreview = new CameraPreview(getContext(), mCamera, activity);
    mPreview.setCameraDisplayOrientation(activity, CAMERA_ID, mCamera);
    preview = (FrameLayout) view.findViewById(R.id.tvCamera);
    preview.addView(mPreview);
    ivCaptureImage = (ImageView) view.findViewById(R.id.ivCaptureImage);
    ivCaptureImage.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mCamera.takePicture(null, null, mPicture); 
        }
    });
}

where newOpenCamera is:

private void newOpenCamera() {
    if (mThread == null) {
        mThread = new CameraHandlerThread();
    }

    synchronized (mThread) {
        mThread.openCamera();
        mCamera = mThread.getCamera();
    }
}

I have ran the debugger and can see that the line where the error occurs (mCamera.takePicture(...) in launchCamera()) gets called but the error gets thrown before the PictureCallback. The error is:

E/UncaughtException: java.lang.RuntimeException: takePicture failed
        at android.hardware.Camera.native_takePicture(Native Method)
        at android.hardware.Camera.takePicture(Camera.java:1523)
        at android.hardware.Camera.takePicture(Camera.java:1468)
        at com.myapp.myapp.camera.CameraFragment$2.onClick(CameraFragment.java:175)
        at android.view.View.performClick(View.java:5697)
        at android.view.View$PerformClick.run(View.java:22526)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:158)
        at android.app.ActivityThread.main(ActivityThread.java:7229)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
05-28 17:09:22.600 1171-1171/com.myapp.myapp E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.myapp.myapp, PID: 1171
    java.lang.RuntimeException: takePicture failed
        at android.hardware.Camera.native_takePicture(Native Method)
        at android.hardware.Camera.takePicture(Camera.java:1523)
        at android.hardware.Camera.takePicture(Camera.java:1468)
        at com.myapp.myapp.camera.CameraFragment$2.onClick(CameraFragment.java:175)
        at android.view.View.performClick(View.java:5697)
        at android.view.View$PerformClick.run(View.java:22526)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:158)
        at android.app.ActivityThread.main(ActivityThread.java:7229)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

Does anyone know what could be wrong? As you can see I always get two of the same error with every one picture taken.

Any help is HIGHLY appreciated, cheers.

Edit:

I have put guards to stop single touches registering as multi as described here: java.lang.RuntimeException: takePicture failed

Still no luck

eyes enberg
  • 556
  • 1
  • 8
  • 30

5 Answers5

0

I would advise you to use third-party libraries.

Android Camera Library Comparison Fotoapparat vs. CameraKit

tim4dev
  • 2,846
  • 2
  • 24
  • 30
0

I think you forgot to call startPreview() method on your camera object. From the official documentation:

6.Important: Call startPreview() to start updating the preview surface. Preview must be started before you can take a picture.

https://developer.android.com/reference/android/hardware/Camera

Alex
  • 9,102
  • 3
  • 31
  • 35
0

Use this way to open camera using surface view Java Code

public class CameraOverlayActivity extends AppCompatActivity implements SurfaceHolder.Callback {
    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    boolean previewing = false;
    LayoutInflater controlInflater = null;

    private File videoPath;
    private ImageView imgCapture;
    int camBackId;
    String strVideoFolderPath;
    private ProgressDialog progressDialog;
    Camera.Parameters parameters;
    public boolean hasFlash;
    public boolean camRotation = false;
    private RelativeLayout relativeLayout;

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

        relativeLayout = findViewById(R.id.control);

        camBackId = Camera.CameraInfo.CAMERA_FACING_BACK;
        hasFlash = this.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
        surfaceView = findViewById(R.id.surface);
        progressDialog = new ProgressDialog(this);
        progressDialog.setTitle(null);
        progressDialog.setCancelable(false);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        strVideoFolderPath = Environment.getExternalStorageDirectory().getAbsolutePath();
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        controlInflater = LayoutInflater.from(getBaseContext());
        videoPath = new File(Environment.getExternalStorageDirectory() + "/sw/raw");
        if (videoPath.exists()) {
            if (videoPath.isDirectory()) {
                if (videoPath.listFiles().length != 0) {
                    String[] children = videoPath.list();
                    for (int i = 0; i < children.length; i++) {
                        new File(videoPath, children[i]).delete();
                    }
                }
            }
        }
        if (!videoPath.exists()) {
            videoPath.mkdirs();
        }

        imgCapture = findViewById(R.id.img_capture);
        imgCapture.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (camera != null) {
                    if (previewing) {
                        System.gc();
                        try {
                            capturePhoto();
                        } catch (Exception e) {
                            Log.v("ERRORR", e.getMessage());
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

    }

    public void capturePhoto() throws Exception {
        camera.takePicture(null, null, myPictureCallback_JPG);

    }

    @Override
    protected void onResume() {
        super.onResume();
        Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
    }

    Camera.PictureCallback myPictureCallback_JPG = new Camera.PictureCallback() {

        @Override
        public void onPictureTaken(byte[] arg0, Camera arg1) {
            // TODO Auto-generated method stub
            FileOutputStream outStream = null;
            //camera.startPreview();
            try {
                Date date = new Date();
                String filename = "/rec" + date.toString().replace(" ", "_").replace(":", "_") + ".jpg";
                filename = filename.replace("+", "");
                File file = new File(Environment.getExternalStorageDirectory() + "/Switch It");
                if (!file.exists())
                    file.mkdirs();
                outStream = new FileOutputStream(file + filename);
                outStream.write(arg0);
                outStream.close();
                Log.v("File_Path", file.getAbsolutePath());
                Intent returnIntent = new Intent();
                returnIntent.putExtra("img_capture", file.getAbsolutePath() + filename);
                setResult(Activity.RESULT_OK, returnIntent);
                finish();
            } catch (FileNotFoundException e) {
                Log.e("ERROR 1", e.getMessage());
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("ERROR 2", e.getMessage());
            } finally {
            }
        }
    };


    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
        // TODO Auto-generated method stub
        if (previewing) {
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null) {
            try {
                camera.setPreviewDisplay(surfaceHolder);
                parameters = camera.getParameters();
                if (getPackageManager().hasSystemFeature("android.hardware.camera.autofocus")) {
                    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                }

                camera.startPreview();
                if (hasFlash) {
                    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                }
                camera.setParameters(parameters);
                previewing = true;

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera = Camera.open();
        if (android.os.Build.VERSION.SDK_INT > 7) {
            Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
            if (display.getRotation() == Surface.ROTATION_0) {
                camera.setDisplayOrientation(90);
                camRotation = true;
            }
        }


    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        if (camera != null) {
            camera.stopPreview();
            camera.release();
            camera = null;
            previewing = false;
        }
    }

}

XML code

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/control"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <SurfaceView
        android:id="@+id/surface"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />




    <ImageView
        android:id="@+id/img_capture"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="5dp"
        android:src="@drawable/ic_lens_black_24dp" />


</RelativeLayout>
Milan Pansuriya
  • 2,521
  • 1
  • 19
  • 33
0

Check whether the permission for using the Camera has been set for that particular application. Go to Settings -> Apps -> "Your app name" -> Permissions -> Turn on the permission for Camera. Also make sure that the permission has been set in the manifest.xml file. It is given as:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Check out this link for more details:

https://developer.android.com/guide/topics/media/camera

0

Try this one works for me and check permission given in the manifest file.

 mCamera = Camera.open(id);
 setCameraDisplayOrientation(mContext, id, mCamera);
 mCamera.setPreviewDisplay(new DummySurfaceHolder());
 SurfaceTexture st = new SurfaceTexture(MODE_PRIVATE);
 mCamera.setPreviewTexture(st);

 mCamera.startPreview();
 mCamera.autoFocus(new Camera.AutoFocusCallback() {
    @Override
     public void onAutoFocus(boolean b, Camera camera) {

      try {
         Thread.sleep(500);
       } catch (InterruptedException e) {
         e.printStackTrace();
       }

      mCamera.takePicture(null, null, null, new PictureCapture(mContext));

       }
     });
Mohd Saquib
  • 580
  • 4
  • 14