使用自定义相机拍照时的RuntimeException - “takePicture failed”

时间:2018-05-28 16:16:39

标签: android

错误发生在CameraFragment内 - 一个只包含FrameLayout(用于保存相机预览)和ImageButton(用于捕获图像)的片段。在我的片段中,我有一个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();

    }
};

我从HandlerThread获取了我的Camera实例:

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

然后我在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); 
        }
    });
}

其中newOpenCamera是:

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

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

我运行了调试器并且可以看到发生错误的行(launchCamera()中的mCamera.takePicture(...))被调用,但错误在PictureCallback之前被抛出。错误是:

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)

有谁知道什么可能是错的?正如您所看到的,每拍一张照片,我总会得到两个相同的错误。

任何帮助都非常感谢,欢呼。

编辑:

我已经设置了警卫来阻止单个触摸注册为多个,如下所述:java.lang.RuntimeException: takePicture failed

仍然没有运气

5 个答案:

答案 0 :(得分:0)

答案 1 :(得分:0)

我认为您忘记在相机对象上调用startPreview()方法。 从官方文档:

  

6.Important:调用startPreview()开始更新预览曲面。必须先开始预览才能拍照。

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

答案 2 :(得分:0)

使用这种方式使用表面视图打开相机 Java代码

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代码

<?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>

答案 3 :(得分:0)

检查是否已为该特定应用程序设置了使用相机的权限。转到设置 - &gt;应用 - &gt; “您的应用名称” - &gt;权限 - &gt;打开相机的权限。 还要确保已在manifest.xml文件中设置了权限。它被命名为:

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

查看此链接了解更多详情:

  

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

答案 4 :(得分:0)

尝试这个适用于我,并检查清单文件中给出的权限。

import javax.swing.*;
import java.util.List;

public class main {
    public static void main(String[] args) {
    JFrame frame = new JFrame();
    JTextField textField = new JTextField();

    List<JButton> list =  Buttons.generateButtons(frame);
    String displayOnTextField = Buttons.displayOnTextField(list,textField);


    frame.setSize(400,600);
    textField.setBounds(150,40,150,30);
    frame.add(textField);
    frame.setLayout(null);
    frame.setVisible(true);

    }
}