Android 致命异常-在Camera.release()被称为HTC ONE M9之后使用Camera

Android 致命异常-在Camera.release()被称为HTC ONE M9之后使用Camera,android,android-studio,exception,camera,release,Android,Android Studio,Exception,Camera,Release,我在检查我的surfaceView项目是否工作正常,所以我在我妻子的Galaxy s7 G930F上试过,效果很好,当我试着在我的HTC ONE M9上运行时,它甚至没有移动,一直在崩溃。这是一个奇怪的问题,两款手机都在安卓6上运行。尝试运行时,我附加了一个日志: E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.arturs.androidmirrorapplicationv2, PID: 1

我在检查我的surfaceView项目是否工作正常,所以我在我妻子的Galaxy s7 G930F上试过,效果很好,当我试着在我的HTC ONE M9上运行时,它甚至没有移动,一直在崩溃。这是一个奇怪的问题,两款手机都在安卓6上运行。尝试运行时,我附加了一个日志:

 E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.example.arturs.androidmirrorapplicationv2, PID: 15974
              java.lang.RuntimeException: Camera is being used after Camera.release() was called
                  at android.hardware.Camera.setPreviewSurface(Native Method)
                  at android.hardware.Camera.setPreviewDisplay(Camera.java:923)
                  at com.example.arturs.androidmirrorapplicationv2.CameraView.surfaceCreated(CameraView.java:46)
                  at android.view.SurfaceView.updateWindow(SurfaceView.java:582)
                  at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:177)
                  at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:944)
                  at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2152)
                  at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1174)
                  at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6241)
                  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:873)
                  at android.view.Choreographer.doCallbacks(Choreographer.java:676)
                  at android.view.Choreographer.doFrame(Choreographer.java:606)
                  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:859)
                  at android.os.Handler.handleCallback(Handler.java:739)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:168)
Disconnected from the target VM, address: 'localhost:8602', transport: 'socket'
                      at android.app.ActivityThread.main(ActivityThread.java:5845)
                      at java.lang.reflect.Method.invoke(Native Method)
我的其余代码如上图所示:MainActivity类

import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

private Camera mCamera;
private CameraView mCameraView;
private static final String TAG = "MainActivity";

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


@Override
protected void onResume(){
    super.onResume();


    try{
        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
            //pyta użytkownika o autoryzację - potrzebne w androidzie => 6.0 tzw. run permission
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.CAMERA}, 50);
        else

        mCamera = openFrontFacingCamera();
        mCameraView = new CameraView(this, mCamera);
        setContentView(mCameraView);
    } catch (Exception e){
        finish();
    }
}

@Override
protected void onPause(){
    if(mCamera != null){
        mCamera.release();
        mCamera = null;
    }
    super.onPause();
}


public Camera openFrontFacingCamera() {



    int cameraCount = 0;
    Camera cam = null;
    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
    cameraCount = Camera.getNumberOfCameras();
    for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
        Camera.getCameraInfo(camIdx, cameraInfo);
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            try {
                cam = Camera.open(camIdx);
            } catch (RuntimeException e) {
                Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
            }
        }
    }

    return cam;
    }
}
导入android.content.pm.PackageManager;
导入android.hardware.Camera;
导入android.os.Bundle;
导入android.support.v4.app.ActivityCompat;
导入android.support.v4.content.ContextCompat;
导入android.support.v7.app.AppActivity;
导入android.util.Log;
公共类MainActivity扩展了AppCompatActivity{
私人摄像机麦卡梅拉;
私人摄影师麦卡梅拉维;
私有静态最终字符串TAG=“MainActivity”;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@凌驾
受保护的void onResume(){
super.onResume();
试一试{
if(ContextCompat.checkSelfPermission(this,android.Manifest.permission.CAMERA)!=PackageManager.permission\u已授予)
//pyta użytkownika o autoryzację-potrzebne w androidzie=>6.0 tzw.运行权限
ActivityCompat.requestPermissions(这个新字符串[]{android.Manifest.permission.CAMERA},50);
其他的
mCamera=openFrontFacingCamera();
mCameraView=新的CameraView(这是mCamera);
setContentView(mCameraView);
}捕获(例外e){
完成();
}
}
@凌驾
受保护的void onPause(){
if(mCamera!=null){
mCamera.release();
mCamera=null;
}
super.onPause();
}
公共摄像机openFrontFacingCamera(){
int cameraCount=0;
摄像机摄像机=null;
Camera.CameraInfo CameraInfo=新的Camera.CameraInfo();
cameraCount=Camera.getNumberOfCameras();
对于(int-camIdx=0;camIdx
喀麦隆人阶级

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Surface;
import android.view.Display;
import android.view.WindowManager;
import java.io.IOException;
import java.util.List;


public class CameraView extends SurfaceView implements SurfaceHolder.Callback{


private Camera mCamera;
private View mView;
private WindowManager display;
private Context mContext;
private static final String cameraPreview = "CameraView";
private static final String APP_CLASS = "APP_CLASS";
private static final String Bug = "Bug";

public CameraView(Context context, Camera mCamera) {
    super(context);

    mContext = context;

    this.mCamera = mCamera;
    mCamera.setDisplayOrientation(90);

    SurfaceHolder holder = getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}


@Override
public void surfaceCreated(SurfaceHolder holder) {
    try{
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
    } catch (IOException e) {
        Log.e(cameraPreview, "The failure of the camera settings");
    }
}


@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    Camera.Parameters params = mCamera.getParameters();
    List<Camera.Size> sizes = params.getSupportedPreviewSizes();
    Camera.Size optionalSize = getOptimalPreviewSize(sizes, width, height);
    params.setPreviewSize(optionalSize.width, optionalSize.height);
    mCamera.setParameters(params);

    boolean isPreviewRunning = true;

    if (isPreviewRunning)
    {
        mCamera.stopPreview();
    }

    Parameters parameters = mCamera.getParameters();
    Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    width = display.getWidth();
    height = display.getHeight();

    if(display.getRotation() == Surface.ROTATION_0)
    {
        parameters.setPreviewSize(height, width);
        mCamera.setDisplayOrientation(90);
    }

    if(display.getRotation() == Surface.ROTATION_90)
    {
        parameters.setPreviewSize(width, height);
        mCamera.setDisplayOrientation(0);
    }

    if(display.getRotation() == Surface.ROTATION_180)
    {
        parameters.setPreviewSize(height, width);
        mCamera.setDisplayOrientation(270);
    }

    if(display.getRotation() == Surface.ROTATION_270)
    {
        parameters.setPreviewSize(width, height);
        mCamera.setDisplayOrientation(180);
    }

    try{
    mCamera.setParameters(parameters);
    previewCamera(holder);
    mCamera.startPreview();}
    catch(Exception e){
        Log.e(Bug, "setting Parameters Failed" + e.getLocalizedMessage());

    }
}

public void previewCamera(SurfaceHolder holder)
{
    try
    {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
        boolean isPreviewRunning = true;
    }
    catch(Exception e)
    {
        Log.d(APP_CLASS, "Cannot start preview", e);
    }
}

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

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {

    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio=(double)h / w;

    if (sizes == null) return null;

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

    int targetHeight = h;

    for (Camera.Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Camera.Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;


 }

}
导入android.content.Context;
导入android.hardware.Camera;
导入android.hardware.Camera.Parameters;
导入android.util.Log;
导入android.view.SurfaceHolder;
导入android.view.SurfaceView;
导入android.view.view;
导入android.view.Surface;
导入android.view.Display;
导入android.view.WindowManager;
导入java.io.IOException;
导入java.util.List;
公共类CameraView扩展了SurfaceView,实现了SurfaceHolder.Callback{
私人摄像机麦卡梅拉;
私有视图;
专用窗口管理器显示;
私有上下文;
私有静态最终字符串cameraPreview=“CameraView”;
私有静态最终字符串APP\u CLASS=“APP\u CLASS”;
私有静态最终字符串Bug=“Bug”;
公共摄像机视图(上下文,摄像机mCamera){
超级(上下文);
mContext=上下文;
this.mCamera=mCamera;
mCamera.setDisplayOrientation(90);
SurfaceHolder holder=getHolder();
holder.addCallback(本);
夹持器。设置类型(表面夹持器。表面夹持器类型推压缓冲);
}
@凌驾
已创建的公共空白表面(表面持有人){
试一试{
mCamera.setPreviewDisplay(支架);
mCamera.startPreview();
}捕获(IOE异常){
Log.e(cameraPreview,“摄像头设置失败”);
}
}
@凌驾
公共空白表面更改(表面文件夹持有者、整型格式、整型宽度、整型高度){
Camera.Parameters params=mCamera.getParameters();
列表大小=params.getSupportedPreviewSizes();
Camera.Size optionalSize=getOptimalPreviewSize(尺寸、宽度、高度);
参数setPreviewSize(optionalSize.width、optionalSize.height);
mCamera.setParameters(参数);
布尔值isPreviewRunning=true;
如果(iPreviewRunning)
{
mCamera.stopPreview();
}
Parameters=mCamera.getParameters();
Display Display=((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
宽度=display.getWidth();
高度=display.getHeight();
if(display.getRotation()==Surface.ROTATION\u 0)
{
参数.setPreviewSize(高度、宽度);
mCamera.setDisplayOrientation(90);
}
if(display.getRotation()==Surface.ROTATION_90)
{
参数。setPreviewSize(宽度、高度);
mCamera.setDisplayOrientation(0);
}
if(display.getRotation()==Surface.ROTATION_180)
{
参数.setPreviewSize(高度、宽度);
mCamera.setDisplayOrientation(270);
}
if(display.getRotation()==Surface.ROTATION_270)
{
参数。setPreviewSize(宽度、高度);
mCamera.setDisplayOrientation(180);
}
试一试{
mCamera.setParameters(参数);
预检照相机(持有人);
mCamera.startPreview();}
捕获(例外e){
Log.e(错误,“设置参数失败”+e.getLocalizedMessage());
}
}
公共无效预览照相机(表面持有人)
{
尝试
{
mCamera.setPreviewDisplay(支架);
mCamera.startPreview();
布尔值isPreviewRunning=true;
}
捕获(例外e)
{
Log.d(应用程序类,“无法启动预览”,e);
}
}
@凌驾
公共空间表面覆盖(表面覆盖物持有人){
mCamera.release();
mCamera=null;
}
私人相机。大小getOptimalPreviewSize(列表大小,整数w,整数h){
最终双纵横比公差=0.1;
双目标率=(双)高/低;
如果(size==null)返回null;
照相机。大小优化大小=空;
double minDiff=double.MAX_值;
int targetHeight=h;
用于(相机尺寸:尺寸){
双重的
    package com.example.arturs.androidmirrorapplicationv2;

import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {

private CameraView mCameraView;
private Camera mCamera;
private static final String TAG = " => Main Activity: ";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mCamera = openFrontFacingCamera();
    setContentView(R.layout.activity_main);

}


@Override
protected void onResume() {
    super.onResume();

//
//            if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
//                //pyta użytkownika o autoryzację - potrzebne w androidzie => 6.0 tzw. run permission
//                ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.CAMERA}, 50);
//            else

            Log.d(TAG, " -> OnResume");
        try {
            mCamera = openFrontFacingCamera();
            if (mCamera != null) {
                mCameraView = new CameraView(this, mCamera);
                setContentView(mCameraView);
            } else {
                Log.d(TAG, " = Camera == NULL");
            }

        } catch (Exception e) {
            e.printStackTrace();
            finish();
        }

        Log.d(TAG, " <- OnResume");


}

@Override
protected void onPause(){
    Log.d(TAG, " -> onPause");
    if(mCamera != null){
        mCamera.release();
        mCamera = null;
    }
    super.onPause();
    Log.d(TAG, " <- onPause");
}


public Camera openFrontFacingCamera() {

//        if (mCamera != null) {
//            mCamera.release();
//            mCamera = null;}

    int cameraCount = 0;
    Camera cam = null;
    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
    cameraCount = Camera.getNumberOfCameras();
    for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
        Camera.getCameraInfo(camIdx, cameraInfo);
        Log.d(TAG, "Camera Info: "+cameraInfo.facing);
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            try {
                return Camera.open(camIdx);
            } catch (RuntimeException e) {
                Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
            }
        }
    }

    return null;
}
}
    package com.example.arturs.androidmirrorapplicationv2;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Surface;
import android.view.Display;
import android.view.WindowManager;
import java.io.IOException;
import java.util.List;


public class CameraView extends SurfaceView implements SurfaceHolder.Callback{


private Camera mCamera;
private View mView;
private WindowManager display;
private Context mContext;
private static final String cameraPreview = "CameraView";
private static final String APP_CLASS = "APP_CLASS";
private static final String Bug = "Bug";

public CameraView(Context context, Camera mCamera) {
    super(context);

    mContext = context;

    this.mCamera = mCamera;
    mCamera.setDisplayOrientation(90);

    SurfaceHolder holder = getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}


@Override
public void surfaceCreated(SurfaceHolder holder) {
    try{
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
    } catch (IOException e) {
        e.printStackTrace();
        Log.e(cameraPreview, "The failure of the camera settings");
    }
}


@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    Camera.Parameters params = mCamera.getParameters();
    List<Camera.Size> sizes = params.getSupportedPreviewSizes();
    Camera.Size optionalSize = getOptimalPreviewSize(sizes, width, height);
    params.setPreviewSize(optionalSize.width, optionalSize.height);
    mCamera.setParameters(params);


    Parameters parameters = mCamera.getParameters();
    Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();


    if(display.getRotation() == Surface.ROTATION_0)
    {
        mCamera.setDisplayOrientation(90);
    }

    if(display.getRotation() == Surface.ROTATION_90)
    {
        mCamera.setDisplayOrientation(0);
    }

    if(display.getRotation() == Surface.ROTATION_180)
    {
        mCamera.setDisplayOrientation(270);
    }

    if(display.getRotation() == Surface.ROTATION_270)
    {
        mCamera.setDisplayOrientation(180);
    }

    try{
    mCamera.setParameters(parameters);
    previewCamera(holder);
    mCamera.startPreview();}
    catch(Exception e){
        e.printStackTrace();
        Log.e(Bug, "setting Parameters Failed" + e.getLocalizedMessage());

    }
}

public void previewCamera(SurfaceHolder holder)
{
    try
    {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
        boolean isPreviewRunning = true;
    }
    catch(Exception e)
    {
        e.printStackTrace();
        Log.d(APP_CLASS, "Cannot start preview", e);
    }
}

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

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {

    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio=(double)h / w;

    if (sizes == null) return null;

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

    int targetHeight = h;

    for (Camera.Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Camera.Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

}