APP实例未被破坏 - Android

时间:2015-12-02 18:18:27

标签: android android-studio android-camera android-ondestroy

视频录制应用不会被正确销毁。当我按“返回”按钮时,“相机应用程序”处于“暂停”()。在启动APP的新实例时,视频录制失败。如果我手动杀死以前的实例并重新运行APP它的工作完美。根据我的假设,实现杀死和释放相机的所有生命周期。但集成或调用可能会产生问题。请帮忙解决一下。

CameraPreview类

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private MyDrawing md;

public CameraPreview(Context context, Camera camera) {
    super(context);
    mCamera = camera;
    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) {
    try {
        // create the surface and start camera preview
        if (mCamera == null) {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        }
    } catch (IOException e) {
        Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
    }
}

public void refreshCamera(Camera camera) {
    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
    }
    // set preview size and make any resize, rotate or
    // reformatting changes here
    // start preview with new settings
    setCamera(camera);
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
        //startFaceDetection();
    } catch (Exception e) {
        Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
    }
}

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.
    refreshCamera(mCamera);
}

public void setCamera(Camera camera) {
    //method to set a camera instance
    mCamera = camera;
    mCamera.setFaceDetectionListener(faceDetectionListener);
    startFaceDetection();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub
     mCamera.release();
}

private Camera.FaceDetectionListener faceDetectionListener = new Camera.FaceDetectionListener() {

    @Override
    public void onFaceDetection(Camera.Face[] faces, Camera c) {

        if (faces.length > 0) {

            Log.d("FaceDetection", "face detected X and Y are as: " + faces.length +
                    " Face 1 Location X: " + faces[0].rect.centerX() +
                    "Y: " + faces[0].rect.centerY() +" LIES IN "+(MyDrawing.w-MyDrawing.radius) +"--"+(MyDrawing.w+MyDrawing.radius));

            if(faces[0].rect.centerX()>=0 && faces[0].rect.centerX()<115 )
            {
                Log.d("ALERT = ", "Detection Started" );
                AndroidVideoCaptureExample.capture.setText("Recording/ stopNsave ");
                AndroidVideoCaptureExample.faceDetect();
            }

        } else {
            Log.d("FaceDetection", "circle cordinates are as: " + (MyDrawing.w-MyDrawing.radius) +"cX"+ MyDrawing.radius+"cY");

        }
    }
};

public void startFaceDetection(){
    // Try starting Face Detection
    Camera.Parameters params = mCamera.getParameters();

    // start face detection only *after* preview has started
    if (params.getMaxNumDetectedFaces() > 0){
        // camera supports face detection, so can start it:
        mCamera.startFaceDetection();
    }
}
}

主要

  public class AndroidVideoCaptureExample extends Activity {
     private static Camera mCamera;
     private static  int vWidth,vHeight;
     private CameraPreview mPreview;
     public static  MediaRecorder mediaRecorder;
     public static Button capture, switchCamera;
     private Context myContext;
     private FrameLayout cameraPreview;
     private boolean cameraFront = false;
     private static int desiredwidth=640, desiredheight=360;
     private MyDrawing md;
     public static boolean vRecording = false; 
@Override
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        myContext = this;
        initialize();
        Log.d("FaceDetection", "face detected BASEER" );
    }

    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_FRONT) {
                cameraId = i;
                cameraFront = true;
                break;
            }
        }
        return cameraId;
    }

    public void onResume() {
        super.onResume();
        if (!hasCamera(myContext)) {
            Toast toast = Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG);
            toast.show();
            finish();
        }
        if (mCamera == null) {
            // if the front facing camera does not exist
            if (findFrontFacingCamera() < 0) {
                Toast.makeText(this, "No front facing camera found.", Toast.LENGTH_LONG).show();
                switchCamera.setVisibility(View.GONE);
            }
            mCamera = Camera.open(findFrontFacingCamera());
            mCamera.setDisplayOrientation(90);
            mPreview.refreshCamera(mCamera);

        }
    }

    public void initialize() {
        cameraPreview = (FrameLayout) findViewById(R.id.camera_preview);
        mPreview = new CameraPreview(myContext, mCamera);
        cameraPreview.addView(mPreview);
        capture = (Button) findViewById(R.id.button_capture);
        capture.setOnClickListener(captrureListener);

    }


    @Override
    protected void onPause() {
        super.onPause();
        // when on Pause, release camera in order to be used from other
        // applications
        releaseCamera();
    }

    private boolean hasCamera(Context context) {
        // check if the device has camera
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {

            return true;

        } else {
            return false;
        }
    }

    static boolean  recording = false;
    OnClickListener captrureListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            if (recording) {
                // stop recording and release camera
                mediaRecorder.stop(); // stop the recording
                releaseMediaRecorder(); // release the MediaRecorder object
                Toast.makeText(AndroidVideoCaptureExample.this, "Video captured!", Toast.LENGTH_LONG).show();

                Toast.makeText(AndroidVideoCaptureExample.this, vWidth+"BY"+vHeight, Toast.LENGTH_LONG).show();

                recording = false;
            }

        }
    };


    public static void faceDetect()
    {
        prepareMediaRecorder();
        recording = true;
        mediaRecorder.start();
    }




    private static void releaseMediaRecorder() {
        if (mediaRecorder != null) {
            mediaRecorder.reset(); // clear recorder configuration
            mediaRecorder.release(); // release the recorder object
            mediaRecorder = null;
            mCamera.lock(); // lock camera for later use
        }
    }

    private static boolean prepareMediaRecorder() {

        List<Camera.Size> videosizes = mCamera.getParameters().getSupportedVideoSizes();
        Camera.Size videosize = videosizes.get(1);
        Camera.Size optimalVideoSize = getOptimalPreviewSize(videosize, desiredwidth, desiredheight);
        vWidth = optimalVideoSize.width;//mCamera.getParameters().getPreviewSize().width;
        vHeight = optimalVideoSize.height;//mCamera.getParameters().getPreviewSize().height;
        mediaRecorder = new MediaRecorder();
        mCamera.unlock();
        mediaRecorder.setCamera(mCamera);
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
        mediaRecorder.setVideoEncodingBitRate(512* 1000);
        mediaRecorder.setVideoFrameRate(15);
        mediaRecorder.setVideoSize(optimalVideoSize.width, optimalVideoSize.height);
        mediaRecorder.setOutputFile("/sdcard/myvideo.mp4");
        mediaRecorder.setMaxDuration(600000); // Set max duration 60 sec.
        mediaRecorder.setMaxFileSize(50000000); // Set max file size 50M

        try {
            mediaRecorder.prepare();
        } catch (IllegalStateException e) {
            releaseMediaRecorder();
            return false;
        } catch (IOException e) {
            releaseMediaRecorder();
            return false;
        }
        return true;

    }

    private void releaseCamera() {
        // stop and release camera
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }

    private static  Camera.Size getOptimalPreviewSize(Camera.Size sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.2;
        double targetRatio = (double) w / h;
        if (sizes == null)
            return null;

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

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
         Camera.Size size = sizes;

            Log.d("Camera", "Checking size " + size.width + "w " + size.height
                    + "h");
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) <= ASPECT_TOLERANCE)
            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
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }

        }
        return optimalSize;
    }


    }

错误日志

  

错误/崩溃:如果应用程序进入前台并重新打开,一旦检测到面部(此检测开始录制视频)应用程序崩溃并出现以下错误。

 E/MediaRecorder: start failed: -38
 D/AndroidRuntime: Shutting down VM
 W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x42230c08)
 E/AndroidRuntime: FATAL EXCEPTION: main
 E/AndroidRuntime: Process: com.javacodegeeks.androidvideocaptureexample, PID: 8350
 E/AndroidRuntime: java.lang.IllegalStateException
 E/AndroidRuntime:     at android.media.MediaRecorder.start(Native Method)
 E/AndroidRuntime:     at com.javacodegeeks.androidvideocaptureexample.AndroidVideoCaptureExample.faceDetect(AndroidVideoCaptureExample.java:141)
 E/AndroidRuntime:     at com.javacodegeeks.androidvideocaptureexample.CameraPreview$1.onFaceDetection(CameraPreview.java:105)
 E/AndroidRuntime:     at android.hardware.Camera$EventHandler.handleMessage(Camera.java:1015)
 E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102)
 E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:146)
 E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5635)
 E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method)
 E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:515)
 E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
 E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
 E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:1)

CameraPreview.surfaceDestroyed()释放相机,但未设置size-1。从后台调用应用时,可能会跳过 AndroidVideoCaptureExample.onCreate(),因此将使用带有旧 mCamera 引用的 mPreview 对象。现在,如果在 AndroidVideoCaptureExample.onResume()之前执行 surfaceChanged(),则会调用 mPreview.refreshCamera(mCamera); ,那就搞砸了。

简单的解决方法是将mCamera = null;添加到 CameraPreview.surfaceDestroyed(),并在 CameraPreview.refreshCamera(相机相机)的开头检查mCamera = null;

BTW, CameraPreview.surfaceCreated()包含一些损坏的代码:

if (camera == null) { return; }

您可以简单地删除所有这些块,这些操作将在 refreshChanged()调用的 refreshCamera()中执行。

您还可以从 CameraPreview 构造函数中删除第二个参数。

答案 1 :(得分:0)

删除那些<变量,看看是否能解决您的问题。当您的上一个活动完成后,Android框架可能会使进程和VM保持活动状态,以便在您下次启动应用程序时减少启动开销。发生这种情况时,您的所有static变量都将保留旧值。 (您的static实例也可能会被保留,因此请注意在那里放置任何数据,并且在您的应用启动时永远不要指望Application被调用。)