I am displaying Camera Preview on a Fragment through Surface View. I got everything working fine but the thing that is annoying me is that it takes about 4-5 seconds to start the Preview and things like 'Stop ' during the duration : My XML Files for the SurfaceView which i host in FrameLayout is actually a FrameLayout Instead of a SurfaceView . Is it due to this the Preview takes time. If not So , What May be the Reason behind the Lag. Any Help would be greatly appreciated
The Code for the CameraPreview is :
class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
// SurfaceHolder
private SurfaceHolder mHolder;
// Our Camera.
private Camera mCamera;
// Parent Context.
private Context mContext;
// Camera Sizing (For rotation, orientation changes)
private Camera.Size mPreviewSize;
// List of supported preview sizes
private List<Camera.Size> mSupportedPreviewSizes;
// Flash modes supported by this camera
private List<String> mSupportedFlashModes;
// View holding this camera.
private View mCameraView;
public CameraPreview(Context context, Camera camera, View cameraView) {
super(context);
// Capture the context
mCameraView = cameraView;
mContext = context;
setCamera(camera);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setKeepScreenOn(true);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
/**
* Begin the preview of the camera input.
*/
public void startCameraPreview()
{
try{
mCamera.setPreviewDisplay(mHolder);
new Thread(new Runnable() {
@Override
public void run() {
mCamera.startPreview();
}
}).start();
}
catch(Exception e){
e.printStackTrace();
}
}
/**
* Extract supported preview and flash modes from the camera.
* @param camera
*/
private void setCamera(Camera camera)
{
// Source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
mCamera = camera;
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mSupportedFlashModes = mCamera.getParameters().getSupportedFlashModes();
// Set the camera to Auto Flash mode.
if (mSupportedFlashModes != null && mSupportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO)){
Camera.Parameters parameters = mCamera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
mCamera.setParameters(parameters);
}
requestLayout();
}
/**
* The Surface has been created, now tell the camera where to draw the preview.
* @param holder
*/
public void surfaceCreated(SurfaceHolder holder) {
try {
if(mCamera!=null){
mCamera.setPreviewDisplay(holder);
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Dispose of the camera preview.
* @param holder
*/
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null){
mCamera.stopPreview();
}
}
/**
* React to surface changed events
* @param holder
* @param format
* @param w
* @param h
*/
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 ||mCamera==null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
Camera.Parameters parameters = mCamera.getParameters();
// Set the auto-focus mode to "continuous"
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
// Preview size must exist.
if(mPreviewSize != null) {
Camera.Size previewSize = mPreviewSize;
parameters.setPreviewSize(previewSize.width, previewSize.height);
}
if(cameratype==Camera.CameraInfo.CAMERA_FACING_BACK){
mCamera.setParameters(parameters); //Nothing to be done for the Front Camera here
}
new Thread(new Runnable() {
@Override
public void run() {
mCamera.startPreview();
}
}).start();
} catch (Exception e){
e.printStackTrace();
}
//The Rotating Proble,
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
}
// make any resize, rotate or reformatting changes here
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
mCamera.setDisplayOrientation(90);
} else {
mCamera.setDisplayOrientation(0);
}
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
new Thread(new Runnable() {
@Override
public void run() {
mCamera.startPreview();
}
}).start();
} catch (Exception e) {
Log.d("Newly Added", "Error starting camera preview: " + e.getMessage());
}
}
/**
* Calculate the measurements of the layout
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// Source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null){
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
/**
* Update the layout based on rotation and orientation changes.
* @param changed
* @param left
* @param top
* @param right
* @param bottom
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
// Source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
if (changed) {
final int width = right - left;
final int height = bottom - top;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null){
Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
switch (display.getRotation())
{
case Surface.ROTATION_0:
previewWidth = mPreviewSize.height;
previewHeight = mPreviewSize.width;
mCamera.setDisplayOrientation(90);
break;
case Surface.ROTATION_90:
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
break;
case Surface.ROTATION_180:
previewWidth = mPreviewSize.height;
previewHeight = mPreviewSize.width;
break;
case Surface.ROTATION_270:
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
mCamera.setDisplayOrientation(180);
break;
}
}
final int scaledChildHeight = previewHeight * width / previewWidth;
mCameraView.layout(0, height - scaledChildHeight, width, height);
}
}
/**
*
* @param sizes
* @param width
* @param height
* @return
*/
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height)
{
// Source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
Camera.Size optimalSize = null;
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) height / width;
// Try to find a size match which suits the whole screen minus the menu on the left.
for (Camera.Size size : sizes){
if (size.height != width) continue;
double ratio = (double) size.width / size.height;
if (ratio <= targetRatio + ASPECT_TOLERANCE && ratio >= targetRatio - ASPECT_TOLERANCE){
optimalSize = size;
}
}
// If we cannot find the one that matches the aspect ratio, ignore the requirement.
if (optimalSize == null) {
// TODO : Backup in case we don't get a size.
}
return optimalSize;
}
}
/**
* Picture Callback for handling a picture capture and saving it out to a file.
*/
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
//This One is Just for Getting a File Named after it
ProgressDialog loading=new ProgressDialog(BaseImagesContainer.reference);
loading.setMessage("Getting Image Ready");
loading.show();
File pictureFile = getOutputMediaFile();
if (pictureFile == null){
Toast.makeText(getActivity(), "Image retrieval failed.", Toast.LENGTH_SHORT)
.show();
return;
}
Bitmap bmp = BitmapFactory.decodeByteArray(data,0, data.length);
bmp=rotateImage(90,bmp);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG,1, stream);
byte[] flippedImageByteArray = stream.toByteArray();
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(flippedImageByteArray);
fos.close();
// Restart the camera preview.
safeCameraOpenInView(mCameraView);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//Intent filter=new Intent(BaseImagesContainer.reference, FilterActivity.class);
//filter.putExtra("Bitmap",String.valueOf(pictureFile.getPath()));
//getActivity().startActivity(filter);
// loading.dismiss();
Uri destination = Uri.fromFile(new File(getActivity().getCacheDir(), "cropped"));
Uri source = Uri.fromFile(new File(pictureFile.getPath()));
Crop.of(source, destination).withMaxSize(800,800).start(getActivity());
}
};