自定义相机预览图片

时间:2015-09-01 14:45:21

标签: android android-camera surfaceview preview surfaceholder

我正在制作一个自定义相机,只需拍照并预览图像。我无法预览图像。即使我在拍照后调用了stopPreview方法,也会显示图片,但是当我按下主页并再次恢复应用程序时相机会重置。

public class CameraActivity extends ActionBarActivity {
Camera camera;
private static final String TAG = CameraActivity.class.getName();
private Button captureImageButton;
private Button retakeImageButton;
private Button nextImageButton;
private Button doneButton;
static final String IS_NEW_IMAGE = "isNewImage";
private CameraSurfaceView cameraPreview;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera);
    captureImageButton = (Button) findViewById(R.id.button_capture);
    retakeImageButton = (Button) findViewById(R.id.retakeImage);
    nextImageButton = (Button) findViewById(R.id.nextImage);
    doneButton = (Button) findViewById(R.id.done);
}

@Override
protected void onResume() {
    super.onResume();
    camera = getCameraInstance();
    if (camera != null) {
        cameraPreview = new CameraSurfaceView(this, camera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(cameraPreview);
    }
    captureImageButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (camera != null) {
                camera.takePicture(null, null, mPicture);
            }
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_camera, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

private Camera getCameraInstance() {
    Camera c = null;
    try {
        int backCameraId = findBackFacingCamera();
        if (backCameraId >= 0) {
            c = Camera.open(backCameraId); // attempt to get a Camera instance
        }
    } catch (Exception e) {
        final Snackbar snackBar = Snackbar.make(findViewById(android.R.id.content), "Please shut down all the background applications and try again", Snackbar.LENGTH_LONG);
        ViewGroup snackBarView = (ViewGroup) snackBar.getView();
        snackBarView.setBackgroundColor(getResources().getColor(R.color.PrimaryOrange));
        snackBar.setAction("Go Back", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (getApplicationContext() != null) {
                    snackBar.dismiss();
                    finish();
                }
            }
        });
        snackBar.show();
    }
    return c; // returns null if camera is unavailable
}

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

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        enablePreviewMode();
        camera.stopPreview();
        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null) {
            Log.d(TAG, "Error creating media file, check storage permissions: ");
            return;
        }
        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }

    }
};
public static final int MEDIA_TYPE_IMAGE = 1;

/**
 * Create a file Uri for saving an image or video
 */
private static Uri getOutputMediaFileUri(int type) {
    return Uri.fromFile(getOutputMediaFile(type));
}

/**
 * Create a File for saving an image or video
 */
private static File getOutputMediaFile(int type) {
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), "MyCameraApp");
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (!mediaStorageDir.exists()) {
        if (!mediaStorageDir.mkdirs()) {
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
    File mediaFile;
    mediaFile = new File(mediaStorageDir.getPath() + File.separator +
            "IMG_" + timeStamp + ".png");
    return mediaFile;
}

private void enablePreviewMode() {
    if (captureImageButton != null && retakeImageButton != null && doneButton != null & nextImageButton != null) {
        captureImageButton.setVisibility(View.GONE);
        retakeImageButton.setVisibility(View.VISIBLE);
        retakeImageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent retakeIntent = getIntent();
                if (retakeIntent != null) {
                    finish();
                    retakeIntent.putExtra(IS_NEW_IMAGE, true);
                    startActivity(retakeIntent);
                }
            }
        });
        doneButton.setVisibility(View.VISIBLE);
        doneButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        nextImageButton.setVisibility(View.VISIBLE);
        nextImageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent retakeIntent = getIntent();
                if (retakeIntent != null) {
                    finish();
                    retakeIntent.putExtra(IS_NEW_IMAGE, false);
                    startActivity(retakeIntent);
                }
            }
        });
    }
}

private void releaseCamera() {
    if (camera != null) {
        camera.release();
    }
    if (cameraPreview != null) {
        cameraPreview.getHolder().removeCallback(cameraPreview);
    }
}

private int findBackFacingCamera() {
    int cameraId = -1;
    //Search for the back facing camera
    //get the number of cameras
    int numberOfCameras = Camera.getNumberOfCameras();
    //for every camera check
    for (int i = 0; i < numberOfCameras; i++) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(i, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            cameraId = i;
            break;
        }
    }
    return cameraId;
}

@Override
protected void onPause() {
    super.onPause();
    releaseCamera();
}

@Override
protected void onStop() {
    super.onStop();
    releaseCamera();

}

}

SurfaceView

public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private static final String TAG = CameraSurfaceView.class.getName();

public CameraSurfaceView(Context context, Camera camera) {
    super(context);
    mCamera = camera;

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    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) {
    // The Surface has been created, now tell the camera where to draw the preview.
    try {
        mCamera.setDisplayOrientation(90);
        mCamera.setPreviewDisplay(holder);
        Camera.Parameters params = mCamera.getParameters();
        params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        mCamera.setParameters(params);
        mCamera.startPreview();
    } catch (IOException e) {
        Log.d(TAG, "Error setting camera preview: " + e.getMessage());
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    // empty. Take care of releasing the Camera preview in your activity.
    mCamera.release();
}

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.

    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
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();

    } catch (Exception e) {
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }
}

}

即使普通相机也不能像这样工作。另一种方法是使用2个片段并传递图像但我想它如果android有一些规定。

1 个答案:

答案 0 :(得分:0)

您是否将CameraSurfaceView放入activity_camera.xml? 如果答案是真的,我想我知道如何解决你的问题 您只需要将CameraSurfaceView xml定义提取到独立的xml布局文件中,并在onResume()回调Activity时对其进行充气,然后将其附加到布局根目录,例如调用top level {{ 1}}对象的Layout方法并将您的虚增addChild传递进去,并在CameraSurfaceView onPause()回调时将其分开,例如从顶层移除Activity CameraSurfaceView对象。
总结:
1.膨胀(每次重新充气)并将Layout添加到CameraSurfaceView中的视图层次结构中; 2.从视图层次结构中删除onResume()并将其取消。