I have created custom camera (Compulsory in horizontal mode) to capture image.
But I'm getting problem in some devices like motorola g3 and g4, it works perfectly on samsung device.
Can some help to fix this.
I resolved above problem by creating custom activity file without xml,
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Requires RelativeLayout.
mLayout = new RelativeLayout(this);
setContentView(mLayout);
}
#Override
protected void onResume() {
super.onResume();
//Outter layout
// Set the second argument by your choice.
// Usually, 0 for back-facing camera, 1 for front-facing camera.
// If the OS is pre-gingerbreak, this does not have any effect.
mPreview = new CameraPreview(this, 0, CameraPreview.LayoutMode.FitToParent);
RelativeLayout.LayoutParams previewLayoutParams = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
mLayout.addView(mPreview, 0, previewLayoutParams);
//Capture button
captureButton = new Button(this);
RelativeLayout.LayoutParams bParams = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
bParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
bParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
captureButton.setText("Capture");
mLayout.addView(captureButton, bParams);
captureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mPreview.takePhoto();
}
});
}
Now create CameraPreview class
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static boolean DEBUGGING = true;
private static final String LOG_TAG = "CameraPreviewSample";
private static final String CAMERA_PARAM_ORIENTATION = "orientation";
private static final String CAMERA_PARAM_LANDSCAPE = "landscape";
private static final String CAMERA_PARAM_PORTRAIT = "portrait";
protected Activity mActivity;
private SurfaceHolder mHolder;
protected Camera mCamera;
protected List<Camera.Size> mPreviewSizeList;
protected List<Camera.Size> mPictureSizeList;
protected Camera.Size mPreviewSize;
protected Camera.Size mPictureSize;
private int mSurfaceChangedCallDepth = 0;
private int mCameraId;
private LayoutMode mLayoutMode;
private int mCenterPosX = -1;
private int mCenterPosY;
private CameraApp cameraApp;
private ImageCallback imageCallback;
private List<Camera.Size> mSupportedPreviewSizes;
PreviewReadyCallback mPreviewReadyCallback = null;
public static enum LayoutMode {
FitToParent, // Scale to the size that no side is larger than the parent
NoBlank // Scale to the size that no side is smaller than the parent
};
public interface PreviewReadyCallback {
public void onPreviewReady();
}
/**
* State flag: true when surface's layout size is set and surfaceChanged()
* process has not been completed.
*/
protected boolean mSurfaceConfiguring = false;
public CameraPreview(Activity activity, int cameraId, LayoutMode mode) {
super(activity); // Always necessary
mActivity = activity;
mLayoutMode = mode;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
if (Camera.getNumberOfCameras() > cameraId) {
mCameraId = cameraId;
} else {
mCameraId = 0;
}
} else {
mCameraId = 0;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
mCamera = Camera.open(mCameraId);
} else {
mCamera = Camera.open();
}
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
Camera.Parameters cameraParams = mCamera.getParameters();
mPreviewSizeList = cameraParams.getSupportedPreviewSizes();
mPictureSizeList = cameraParams.getSupportedPictureSizes();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mSurfaceChangedCallDepth++;
doSurfaceChanged(width, height);
mSurfaceChangedCallDepth--;
}
private void doSurfaceChanged(int width, int height) {
mCamera.stopPreview();
Camera.Parameters cameraParams = mCamera.getParameters();
boolean portrait = isPortrait();
// The code in this if-statement is prevented from executed again when surfaceChanged is
// called again due to the change of the layout size in this if-statement.
if (!mSurfaceConfiguring) {
Camera.Size previewSize = determinePreviewSize(portrait, width, height);
Camera.Size pictureSize = determinePictureSize(previewSize);
if (DEBUGGING) { Log.v(LOG_TAG, "Desired Preview Size - w: " + width + ", h: " + height); }
mPreviewSize = previewSize;
mPictureSize = pictureSize;
mSurfaceConfiguring = adjustSurfaceLayoutSize(previewSize, portrait, width, height);
// Continue executing this method if this method is called recursively.
// Recursive call of surfaceChanged is very special case, which is a path from
// the catch clause at the end of this method.
// The later part of this method should be executed as well in the recursive
// invocation of this method, because the layout change made in this recursive
// call will not trigger another invocation of this method.
if (mSurfaceConfiguring && (mSurfaceChangedCallDepth <= 1)) {
return;
}
}
configureCameraParameters(cameraParams, portrait);
mSurfaceConfiguring = false;
try {
mCamera.startPreview();
} catch (Exception e) {
Log.w(LOG_TAG, "Failed to start preview: " + e.getMessage());
// Remove failed size
mPreviewSizeList.remove(mPreviewSize);
mPreviewSize = null;
// Reconfigure
if (mPreviewSizeList.size() > 0) { // prevent infinite loop
surfaceChanged(null, 0, width, height);
} else {
Toast.makeText(mActivity, "Can't start preview", Toast.LENGTH_LONG).show();
Log.w(LOG_TAG, "Gave up starting preview");
}
}
if (null != mPreviewReadyCallback) {
mPreviewReadyCallback.onPreviewReady();
}
}
/**
* #param portrait
* #param reqWidth must be the value of the parameter passed in surfaceChanged
* #param reqHeight must be the value of the parameter passed in surfaceChanged
* #return Camera.Size object that is an element of the list returned from Camera.Parameters.getSupportedPreviewSizes.
*/
protected Camera.Size determinePreviewSize(boolean portrait, int reqWidth, int reqHeight) {
// Meaning of width and height is switched for preview when portrait,
// while it is the same as user's view for surface and metrics.
// That is, width must always be larger than height for setPreviewSize.
int reqPreviewWidth; // requested width in terms of camera hardware
int reqPreviewHeight; // requested height in terms of camera hardware
if (portrait) {
reqPreviewWidth = reqHeight;
reqPreviewHeight = reqWidth;
} else {
reqPreviewWidth = reqWidth;
reqPreviewHeight = reqHeight;
}
if (DEBUGGING) {
Log.v(LOG_TAG, "Listing all supported preview sizes");
for (Camera.Size size : mPreviewSizeList) {
Log.v(LOG_TAG, " w: " + size.width + ", h: " + size.height);
}
Log.v(LOG_TAG, "Listing all supported picture sizes");
for (Camera.Size size : mPictureSizeList) {
Log.v(LOG_TAG, " w: " + size.width + ", h: " + size.height);
}
}
// Adjust surface size with the closest aspect-ratio
float reqRatio = ((float) reqPreviewWidth) / reqPreviewHeight;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
Camera.Size retSize = null;
for (Camera.Size size : mPreviewSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
return retSize;
}
protected Camera.Size determinePictureSize(Camera.Size previewSize) {
Camera.Size retSize = null;
for (Camera.Size size : mPictureSizeList) {
if (size.equals(previewSize)) {
return size;
}
}
if (DEBUGGING) { Log.v(LOG_TAG, "Same picture size not found."); }
// if the preview size is not supported as a picture size
float reqRatio = ((float) previewSize.width) / previewSize.height;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
for (Camera.Size size : mPictureSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
return retSize;
}
protected boolean adjustSurfaceLayoutSize(Camera.Size previewSize, boolean portrait,
int availableWidth, int availableHeight) {
float tmpLayoutHeight, tmpLayoutWidth;
if (portrait) {
tmpLayoutHeight = previewSize.width;
tmpLayoutWidth = previewSize.height;
} else {
tmpLayoutHeight = previewSize.height;
tmpLayoutWidth = previewSize.width;
}
float factH, factW, fact;
factH = availableHeight / tmpLayoutHeight;
factW = availableWidth / tmpLayoutWidth;
if (mLayoutMode == LayoutMode.FitToParent) {
// Select smaller factor, because the surface cannot be set to the size larger than display metrics.
if (factH < factW) {
fact = factH;
} else {
fact = factW;
}
} else {
if (factH < factW) {
fact = factW;
} else {
fact = factH;
}
}
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)this.getLayoutParams();
int layoutHeight = (int) (tmpLayoutHeight * fact);
int layoutWidth = (int) (tmpLayoutWidth * fact);
if (DEBUGGING) {
Log.v(LOG_TAG, "Preview Layout Size - w: " + layoutWidth + ", h: " + layoutHeight);
Log.v(LOG_TAG, "Scale factor: " + fact);
}
boolean layoutChanged;
if ((layoutWidth != this.getWidth()) || (layoutHeight != this.getHeight())) {
layoutParams.height = layoutHeight;
layoutParams.width = layoutWidth;
if (mCenterPosX >= 0) {
layoutParams.topMargin = mCenterPosY - (layoutHeight / 2);
layoutParams.leftMargin = mCenterPosX - (layoutWidth / 2);
}
this.setLayoutParams(layoutParams); // this will trigger another surfaceChanged invocation.
layoutChanged = true;
} else {
layoutChanged = false;
}
return layoutChanged;
}
/**
* #param x X coordinate of center position on the screen. Set to negative value to unset.
* #param y Y coordinate of center position on the screen.
*/
public void setCenterPosition(int x, int y) {
mCenterPosX = x;
mCenterPosY = y;
}
protected void configureCameraParameters(Camera.Parameters cameraParams, boolean portrait) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { // for 2.1 and before
if (portrait) {
//cameraParams.set(CAMERA_PARAM_ORIENTATION, CAMERA_PARAM_PORTRAIT);
cameraParams.set(CAMERA_PARAM_ORIENTATION, CAMERA_PARAM_LANDSCAPE);
} else {
cameraParams.set(CAMERA_PARAM_ORIENTATION, CAMERA_PARAM_LANDSCAPE);
}
} else { // for 2.2 and later
int angle;
Display display = mActivity.getWindowManager().getDefaultDisplay();
switch (display.getRotation()) {
case Surface.ROTATION_0: // This is display orientation
angle = 90; // This is camera orientation
break;
case Surface.ROTATION_90:
angle = 0;
break;
case Surface.ROTATION_180:
angle = 270;
break;
case Surface.ROTATION_270:
angle = 180;
break;
default:
angle = 90;
break;
}
Log.v(LOG_TAG, "angle: " + angle);
mCamera.setDisplayOrientation(angle);
}
cameraParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
cameraParams.setPictureSize(mPictureSize.width, mPictureSize.height);
if (DEBUGGING) {
Log.v(LOG_TAG, "Preview Actual Size - w: " + mPreviewSize.width + ", h: " + mPreviewSize.height);
Log.v(LOG_TAG, "Picture Actual Size - w: " + mPictureSize.width + ", h: " + mPictureSize.height);
}
if (cameraParams.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
cameraParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(cameraParams);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
stop();
}
public void stop() {
if (null == mCamera) {
return;
}
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
public boolean isPortrait() {
return (mActivity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
}
public void setOneShotPreviewCallback(PreviewCallback callback) {
if (null == mCamera) {
return;
}
mCamera.setOneShotPreviewCallback(callback);
}
public void setPreviewCallback(PreviewCallback callback) {
if (null == mCamera) {
return;
}
mCamera.setPreviewCallback(callback);
}
public Camera.Size getPreviewSize() {
return mPreviewSize;
}
public void setOnPreviewReady(PreviewReadyCallback cb) {
mPreviewReadyCallback = cb;
}
public void takePhoto(){
if(mCamera != null){
mCamera.takePicture(null, null, new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] bytes, Camera camera) {
if(bytes.length > 0){
Log.d("CameraPreview","Yes!!! We got an Image");
}
Bitmap capturedBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
//capturedBitmap = Bitmap.createScaledBitmap(capturedBitmap,1196,527,true);
imageCallback = (ImageCallback) mActivity;
imageCallback.resultImage(capturedBitmap);
}
});
}
}
Thats it !!, you are almost done
Just one more thing that you need to create, is interface for getting result in your main activity.
Pls. feel free to ask your query.
Use property android:adjustViewBounds="true"
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:visibility="gone" />
Related
I am using Android Camera API and it works good 16:9 ratio devices on both portrait and landscape modes. But in Samsung S9 18:9 ratio device, on landscape mode the preview looks stretched. On Samsung S9 I got following supported preview sizes, 1920X1080,1440X1080, 1088X1088,1280X720,1056X704, 1024X768, 960X720,800X450,720X720,720X480,640X480,352X288,320X240,256X144,176X144 So optimal preview size is 1920X1080 but actual resolution of device is 2,220 x 1,080. So that it looks stretched.But I need preview on full screen.How default camera preview shows on fullscreen?
#SuppressLint("ClickableViewAccessibility")
#SuppressWarnings("deprecation")
public CameraPreview(Context context, Camera.PreviewCallback previewCallback) {
super(context);
this.previewCallback = previewCallback;
mContext = context;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCameraDisplayOrientation(Context activity,
int cameraId, Camera camera) {
Camera.CameraInfo info =
new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = ((AppCompatActivity) activity).getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
mDisplayOrientation = result;
Log.d(TAG, "setCameraDisplayOrientation: "+mDisplayOrientation);
camera.setDisplayOrientation(result);
}
public void takePhoto(final PictureCallback pCalback) {
mCamera.takePicture(null, null, pCalback);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
//previewCount = 0;
}
try {
mCamera = Camera.open();
//setCameraDisplayOrientation(mContext, 0, mCamera);
/*mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
optimalPreviewSize = getBestAspectPreviewSize(mParameters.getSupportedPreviewSizes(), screenWidth, screenHeight);//Bug Fix for Samsung A8
mParameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
mParameters.setPictureSize(optimalPreviewSize.width, optimalPreviewSize.height);
mParameters.setPreviewFpsRange(30000, 30000);
mCamera.setParameters(mParameters);*/
/*mCamera.setPreviewDisplay(holder);
mCamera.setPreviewCallback(previewCallback);*/
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
//previewCount = 0;
} catch (Exception exception) {
mCamera = null;
//previewCount = 0;
}
if (mCameraPreviewListener != null) {
mCameraPreviewListener.onCameraSurfaceCreated();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
//previewCount = 0;
}
if (mCameraPreviewListener != null) {
mCameraPreviewListener.onCameraSurfaceDestroyed();
}
}
public void stopCamera() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
//previewCount = 0;
}
}
#SuppressWarnings("null")
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
try {
// Now that the size is known, set up the camera parameters and begin
// the preview.
mParameters = mCamera.getParameters();
Log.d("CameraFix", "parameters -> " + mParameters.flatten());
setCameraDisplayOrientation(mContext, 0, mCamera);
mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
//Size optimalPreviewSize = getOptimalPreviewSize(mParameters.getSupportedPreviewSizes(), getWidth(), getHeight());
DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
//Size optimalPreviewSize = getOptimalPreviewSize(mParameters.getSupportedPreviewSizes(), screenWidth, screenHeight, getHeight());
mSupportedPreviewSizes = mParameters.getSupportedPreviewSizes();
optimalPreviewSize = getBestAspectPreviewSize(mParameters.getSupportedPreviewSizes(), screenWidth, screenHeight);//Bug Fix for Samsung A8
Log.d("CameraFix", "optimalPreviewSize.width -> " + optimalPreviewSize.width);
Log.d("CameraFix", "optimalPreviewSize.height -> " + optimalPreviewSize.height);
mParameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
mParameters.setPictureSize(optimalPreviewSize.width, optimalPreviewSize.height);
mParameters.setPreviewFpsRange(30000, 30000);
/*if (mDisplayOrientation == 0 || mDisplayOrientation == 180) {
setLayoutParams(new FrameLayout.LayoutParams(optimalPreviewSize.width, optimalPreviewSize.height,Gravity.CENTER));
}*/
Log.d("CameraFix", "setPreviewFpsRange");
mCamera.setParameters(mParameters);
mCamera.setPreviewDisplay(holder);
//SurfaceTexture st = new SurfaceTexture(10);
//mCamera.setPreviewTexture(st);
mCamera.setPreviewCallback(previewCallback);
mCamera.startPreview();
Log.d("CameraFix", "start preview");
if (mCameraPreviewListener != null) {
mCameraPreviewListener.onCameraSurfaceChanged();
}
} catch (Exception e) {
e.printStackTrace();
Log.d("CameraFix", e.toString());
}
}
public void toggleFlash(boolean flashModeOn) {
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
Parameters parameters = mCamera.getParameters();
if (flashModeOn) {
//parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
parameters.setFlashMode(Parameters.FLASH_MODE_ON);
mCamera.setParameters(parameters);
mCamera.startPreview();
//Toast.makeText(mContext, R.string.flash_mode_on, Toast.LENGTH_SHORT).show();
} else {
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
mCamera.setParameters(parameters);
//Toast.makeText(mContext, R.string.flash_mode_off, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(mContext, R.string.flash_not_available, Toast.LENGTH_SHORT).show();
}
}
/**
* Source for this solution - https://stackoverflow.com/questions/21354313/camera-preview-quality-in-android-is-poor/21354442#21354442
*
* #param supportedPreviewSizes
* #param screenWidth
* #param screenHeight
* #return
*/
private Size getBestAspectPreviewSize(List<Size> supportedPreviewSizes, int screenWidth, int screenHeight) {
double targetRatio = (double) screenWidth / screenHeight;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
for (int i = 0; i < supportedPreviewSizes.size(); i++) {
Size size = supportedPreviewSizes.get(i);
Log.d(TAG, "getBestAspectPreviewSize: supportedPreviewSizes -> "+size.width +"X"+size.height);
}
Log.d(TAG, "getBestAspectPreviewSize: supportedPreviewSizes -> "+supportedPreviewSizes.toString());
Log.d(TAG, "getBestAspectPreviewSize: mDisplayOrientation -> "+mDisplayOrientation);
if (mDisplayOrientation == 90 || mDisplayOrientation == 270) {
Log.d(TAG, "getBestAspectPreviewSize: inside 90 - 270 ");
targetRatio = (double) screenHeight / screenWidth;
}
Log.d(TAG, "getBestAspectPreviewSize: targetRatio -> "+targetRatio);
Collections.sort(supportedPreviewSizes,
Collections.reverseOrder(new SizeComparator()));
for (Size size : supportedPreviewSizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) < minDiff) {
optimalSize = size;
minDiff = Math.abs(ratio - targetRatio);
}
if (minDiff < 0.0d) {
break;
}
}
return (optimalSize);
/*if (mDisplayOrientation == 0 || mDisplayOrientation == 180) {
if (optimalSize != null) {
return mCamera.new Size(optimalSize.height, optimalSize.width);
} else {
return null;
}
}
else{
return (optimalSize);
}*/
//return mCamera.new Size(2220,1080);
}
public int getDisplayOrientation() {
return mDisplayOrientation;
}
public void setDisplayOrientation(int displayOrientation) {
this.mDisplayOrientation = displayOrientation;
}
public Parameters getCameraParameters() {
return mCamera.getParameters();
}
public void setCameraPreviewListener(CameraPreviewListener cameraPreviewListener) {
mCameraPreviewListener = cameraPreviewListener;
}
public interface CameraPreviewListener {
void onCameraSurfaceCreated();
void onCameraSurfaceChanged();
void onCameraSurfaceDestroyed();
void onCameraPreviewStarted();
}
private static class SizeComparator implements
Comparator<Size> {
#Override
public int compare(Size lhs, Size rhs) {
int left = lhs.width * lhs.height;
int right = rhs.width * rhs.height;
if (left < right) {
return (-1);
} else if (left > right) {
return (1);
}
return (0);
}
}
You should check the displayable area of default camera again. I don't think it can display fully without stretch in that resolution. It may have a black area, toolbar, status bar...
There is nothing wrong in your implementation. We have to find the best support preview size compare with surface view which you want to display. In this case, you should make the surface view (1920 x 1080) in center, then add black padding areas on top and bottom.
Please take look into my answer hope it will help, I resolved the stretch issue by the following code, method name might change. I share my implementation, Because I know how hard to implement camera in Android, So please don't hesitate to see the following section.
Invoke loadCamera method in ButtonAction.
private void loadCamera() {
if (CommonUtils.deviceHasCamera(getActivityContext)) {
startBackgroundThread();
mCameraTimeOut=(isPermissionGranted?2500:5000);
if (mTextureView.isAvailable()) {
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
} else {
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}else{
ShowToastUtils.INSTANCE.showCustomToast(getActivityContext, getString(R.string.msg_no_camera));
}
}
Initially SurfaceListener Invoked for Camera
private TextureView.SurfaceTextureListener mSurfaceTextureListener
= new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
int width, int height) {
mCameraTimeOut=(isPermissionGranted?2500:5000);
Log.e(TAG1, "chooseOptimalSize"+"-SurfaceTextureListener ---=>Width---=>"+width);
Log.e(TAG1, "chooseOptimalSize"+"-SurfaceTextureListener ---=>Height---=>"+height);
openCamera(width, height);
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
int width, int height) {
configureTransform(width, height);
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {}
};
To Choose Optimal Preview Size for Texture
//Samsung-S6-choices[0]
//Samsung-S7-edge-choices[6]
//OnePlus-5T-choices[15]
/*Following is used for Camera Preview in TextureView, based on device camera resolution*/
/*
* Given {#code choices} of {#code Size}s supported by a camera, chooses the smallest one whose
* width and height are at least as large as the respective requested values, and whose aspect
* ratio matches with the specified value.
*
* #param choices The list of sizes that the camera supports for the intended output class
* #param width The minimum desired width
* #param height The minimum desired height
* #param aspectRatio The aspect ratio
* #return The optimal {#code Size}, or an arbitrary one if none were big enough
*/
private Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
// Collect the supported resolutions that are at least as big as the preview Surface
int loopCounter=0;
Log.e(TAG1, "Screen-->Width x Height="+screenWidth+" x "+screenHeight);
for (Size size : choices) {
Log.e(TAG1, "chooseOptimalSize:"+size);
}
for (Size size : choices) {
int orientation = getActivityContext.getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
if((size.getWidth()/16) == (size.getHeight()/9) && size.getWidth() <=7680 ) {//8K UHDTV Super Hi-Vision
Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"--LoopPosition---==>"+loopCounter);
return size;
}
} else {
Log.e(TAG1, "chooseOptimalSize:--given--"+size);
if((size.getWidth()/16) == (size.getHeight()/9) && ((size.getWidth() <=1280)||(size.getHeight()<=1920))) {
mCameraRatio=RATIO_16_9;
Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-16:9"+"--LoopPosition---==>"+loopCounter);
return size;
}else if((size.getWidth()/18) == (size.getHeight()/9) && ((size.getWidth() <=2160)||(size.getHeight()<=3840))) {
mCameraRatio=RATIO_18_9;
Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-18:9"+"--LoopPosition---==>"+loopCounter);
return size;
}else if((size.getWidth()/18.5) == (size.getHeight()/9) && ((size.getWidth() <=2160)||(size.getHeight()<=3840))) {
mCameraRatio=RATIO_18_9;
Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-18.5:9"+"--LoopPosition---==>"+loopCounter);
return size;
}else if((width/19) == (height/9) && ((width <=2208)||(height<=3216))) {
mCameraRatio=RATIO_19_9;
Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-19:9"+"--LoopPosition---==>"+loopCounter);
return size;
}else if((size.getWidth()/19.5) == (size.getHeight()/9) && ((size.getWidth() <=3840)||(size.getHeight()<=2160))) {
mCameraRatio=RATIO_19_9;
Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-19.5:9"+"--LoopPosition---==>"+loopCounter);
return size;
}else{
Log.e(TAG1, "chooseOptimalSize"+" not proper aspect resolution");
}
}
loopCounter++;
}
}
To Open Camera
private void openCamera(int width, int height) {
CameraManager manager = (CameraManager) getActivityContext.getSystemService(Context.CAMERA_SERVICE);
try {
Log.e(TAG, "tryAcquire");
if (!mCameraOpenCloseLock.tryAcquire(mCameraTimeOut, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("Time out waiting to lock camera opening.");
}
String mCameraId = manager.getCameraIdList()[cameraId];
// Choose the sizes for camera preview and video recording
characteristics = manager.getCameraCharacteristics(mCameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
try {
mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
maximumZoomLevel = characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
if (map == null) {
throw new RuntimeException("Cannot get available preview/video sizes");
}
mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
/*This Line will configure the Texture size*/
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height, mVideoSize);
int orientation = getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
Log.e(TAG1, "Width" + mPreviewSize.getWidth() + "X Height" + mPreviewSize.getHeight());
mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
} else {
Log.e(TAG1, "Width" + mPreviewSize.getHeight() + "X Height" + mPreviewSize.getWidth());
mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
//S10 preview Size
/* mTextureView.setAspectRatio(1080, 2280);*/
//mTextureView.setAspectRatio(2208, 2944);
}
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
configureTransform(width, height);
}
if (isPermissionGranted) {
manager.openCamera(mCameraId, mStateCallback, null);
}
}catch (Exception ex){ex.printStackTrace();}finally {
map=null;
Runtime.getRuntime().gc();
}
} catch (CameraAccessException e) {
Toast.makeText(getActivityContext, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
//getActivityContext.finish();
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
throw new RuntimeException("Interrupted while trying to lock camera opening.");
}
}
ConfigureTransform method used for orientation handling
/*
* Configures the necessary {#link android.graphics.Matrix} transformation to `mTextureView`.
* This method should not to be called until the camera preview size is determined in
* openCamera, or until the size of `mTextureView` is fixed.
*
* #param viewWidth The width of `mTextureView`
* #param viewHeight The height of `mTextureView`
*/
private void configureTransform(int viewWidth, int viewHeight) {
if (null == mTextureView || null == mPreviewSize) {
return;
}
int rotation = getActivityContext.getWindowManager().getDefaultDisplay().getRotation();
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max((float) viewHeight / mPreviewSize.getHeight(),(float) viewWidth / mPreviewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
}else if (Surface.ROTATION_0 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale=Math.max((float) viewWidth / mPreviewSize.getWidth(), (float) viewHeight / mPreviewSize.getHeight());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(0, centerX, centerY);
}else if(Surface.ROTATION_180== rotation){
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale=Math.max((float) viewWidth / mPreviewSize.getWidth(), (float) viewHeight / mPreviewSize.getHeight());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(0, centerX, centerY);
}
try {
mTextureView.setTransform(matrix);
}catch (Exception ex){ex.printStackTrace();}finally {
bufferRect=null;
viewRect=null;
matrix=null;
}
}
Finally to Start Preview
private void startPreview() {
if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
return;
}
try {
closePreviewSession();
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
//texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
Surface previewSurface = new Surface(texture);
mPreviewBuilder.addTarget(previewSurface);
mCameraDevice.createCaptureSession(Collections.singletonList(previewSurface),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession session) {
mPreviewSession = session;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession session) {
Toast.makeText(getActivityContext, "Failed", Toast.LENGTH_SHORT).show();
}
}, mBackgroundHandler);
//previewSurface=null;
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
In some device the the image become stretched, I'm using surfaceView in may camera preview.
public class vp02ImageCapture extends SuperVP {
private static final String TAG = "vp02ImageCapture";
private Camera camera;
#Bind(R.id.TransparentView) SurfaceView transparentView;
#Bind(R.id.sv_camera) SurfaceView sv;
#Bind(R.id.relative) RelativeLayout rl;
#Bind(R.id.mask) FrameLayout mask;
private ProgressDialog dp;
private boolean front = true;
private SurfaceHolder sh,holderTransparent;
int orient = 1;
private Handler h = new Handler();
View v;
//private UserInfo info;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
v = inflater.inflate(R.layout.vp02imagecapture, null);
ButterKnife.bind(this, v);
sh = sv.getHolder();
holderTransparent = transparentView.getHolder();
holderTransparent.setFormat(PixelFormat.TRANSPARENT);
transparentView.setZOrderMediaOverlay(true);
return v;
}
public int getscrOrientation()
{
Display getOrient = getActivity().getWindowManager().getDefaultDisplay();
int orientation = getOrient.getOrientation();
// Sometimes you may get undefined orientation Value is 0
// simple logic solves the problem compare the screen
// X,Y Co-ordinates and determine the Orientation in such cases
if(orientation==Configuration.ORIENTATION_UNDEFINED){
Configuration config = getResources().getConfiguration();
orientation = config.orientation;
if(orientation== Configuration.ORIENTATION_UNDEFINED){
//if height and widht of screen are equal then
// it is square orientation
if(getOrient.getWidth()==getOrient.getHeight()){
orientation = Configuration.ORIENTATION_SQUARE;
}else{ //if widht is less than height than it is portrait
if(getOrient.getWidth() < getOrient.getHeight()){
orientation = Configuration.ORIENTATION_PORTRAIT;
}else{ // if it is not any of the above it will defineitly be landscape
orientation = Configuration.ORIENTATION_LANDSCAPE;
}
}
}
}
return orientation; // return value 1 is portrait and 2 is Landscape Mode
}
openCamera() method
private void openCamera() {
int cameraId;
if (front) {
cameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
} else{
cameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
}
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = getActivity().getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
final Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
Camera.Size optimalSize = getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
transparentView.requestLayout();
sv.requestLayout();
h.postDelayed(new Runnable() {
#Override
public void run() {
try {
Draw();
// camera.setParameters(parameters);
camera.setPreviewDisplay(sh);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
}, 200);
}
#Override
public void releaseUI() {
rl.setVisibility(View.GONE);
// hideProgressDialog();
camera.release();
}
#Override
public void updateUI() {
super.updateUI();
Log.e("sample","asd " + TAG);
if (TAG.equals("vp02ImageCapture")){
parent.btnNext.setVisibility(View.GONE);
parent.btnBack.setVisibility(View.GONE);
}else{
parent.btnNext.setVisibility(View.VISIBLE);
parent.btnBack.setVisibility(View.VISIBLE);
}
getActivity().setTitle("Image Capture");
rl.setVisibility(View.VISIBLE);
openCamera();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("isfront", front);
}
#OnClick(R.id.btnSwitch)void switchCamera(){
camera.stopPreview();
camera.release();
front = front ? false : true;
openCamera();
}
#OnClick(R.id.btnCapture) void capture(){
// showProgressDialog("Loading...");
camera.takePicture(new Camera.ShutterCallback() {
#Override
public void onShutter() {
}
}, new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
}
}, new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// rotate capture image
Display display = getActivity().getWindowManager().getDefaultDisplay();
int rotation = 0;
switch (display.getRotation()) {
case Surface.ROTATION_0: // This is display orientation
rotation = 90;
break;
case Surface.ROTATION_90:
rotation = 0;
break;
case Surface.ROTATION_180:
rotation = 270;
break;
case Surface.ROTATION_270:
rotation = 180;
break;
}
//Crop image size
Bitmap bitmap = ImageFactory.byteArrayToBitmap(data);
if (front) {
bitmap = rotate(bitmap, rotation);
}
int l = sv.getWidth() / 8;
int t = (sv.getHeight() / 2) - (l*4);
// 2.3 Size of rotated bitmap
int bitWidth = bitmap.getWidth();
int bitHeight = bitmap.getHeight();
Log.e("SIZES", "" + sv.getHeight() + "----" + bitHeight + "-----");
// 3. Size of camera preview on screen
int preWidth = sv.getWidth();
int preHeight = sv.getHeight();
// 4. Scale it.
// Assume you draw Rect as "canvas.drawRect(60, 50, 210, 297, paint);" command
// canvas.drawRect(l,t,l*7,t + l*8,paint1);
// int startx = (l * bitWidth / preWidth);
// int starty = (t * bitHeight / preHeight);
// int endx = ((l * 6) * bitWidth / preWidth);
// int endy = (((t * 4) * bitHeight / preHeight));
int startx = (l * bitWidth / preWidth);
int starty = (t * bitHeight / preHeight);
int endx = ((l * 6) * bitWidth / preWidth);
int endy = (((t + (l*7)) * bitHeight / preHeight));
Log.e("ELIBOY!", "" + l + "----" + t + "------" + l * 7 + "----" + t * 5);
Log.e("ELI!!!!", "" + startx + "----" + starty + "------" + endx + "----" + endy);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
setImageByteArray(byteArray);
setStartX(startx);
setStartY(starty);
setEndX(endx);
setEndY(endy);
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1); //set next page to display ; current page + 1
/*Fragment f = new vp03ImagePreview();
f.setArguments(b);
getParentFragment().getChildFragmentManager().beginTransaction().replace(R.id.imagefrag_container,f).commit();*/
//ScreenManager.getInstance().replaceScreen(Screens.Enroll02b,b);
}
});
}
boolean fromPause = false;
#Override
public void onResume() {
super.onResume();
if(fromPause)
if(((ScreenTransaction)getParentFragment()).viewPager.getCurrentItem()==1)
openCamera();
fromPause = false;
}
#Override
public void onPause() {
super.onPause();
try{
camera.release();
}catch (NullPointerException e){
}
h.removeCallbacksAndMessages(null);
fromPause = true;
//viewPager.removeOnPageChangeListener(viewpagerChangeListener);
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.5;
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;
}
#OnClick(R.id.mask)void autofocus(){
camera.autoFocus(new Camera.AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
}
});
}
public void showProgressDialog(String message){
dp = new ProgressDialog(getActivity());
dp.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dp.setCancelable(false);
dp.setMessage(message);
dp.show();
}
public void hideProgressDialog(){
dp.hide();
}
}
I want to support all screen .
How can I solve this?
in some screen its working but in some specially when its default camera is not in full screen.
I have made this code and its working very well.
public class CameraActivity extends Activity implements Constants.Parameters {
FrameLayout previewFrameLayout;
ImageButton captureButton, switchCamera, flashImageButton, backImageButton;
boolean isFlashEnabled = false, isFlashAvailable = false, isFrontCamera = false;
Handler handler;
private int mCameraId;
private Camera mCamera;
private CameraPreview mCameraPreview;
public final int BACK_CAMERA = 0;
public final int FRONT_CAMERA = 1;
String className = "";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
handler = new Handler();
isFlashAvailable = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
isFrontCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
previewFrameLayout = (FrameLayout) findViewById(R.id.camera_preview);
captureButton = (ImageButton) findViewById(R.id.button_capture);
captureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCamera.takePicture(null, null, mPicture);
}
});
switchCamera = (ImageButton) findViewById(R.id.switchCamera);
switchCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Utils.scaleView(switchCamera);
handler.postDelayed(new Runnable() {
#Override
public void run() {
previewFrameLayout.removeAllViews();
if (mCameraId == BACK_CAMERA) {
flashImageButton.setVisibility(View.INVISIBLE);
mCameraId = FRONT_CAMERA;
mCameraPreview = new CameraPreview(CameraNewActivity.this, FRONT_CAMERA);
previewFrameLayout.addView(mCameraPreview);
} else {
flashImageButton.setVisibility(View.VISIBLE);
mCameraId = BACK_CAMERA;
mCameraPreview = new CameraPreview(CameraNewActivity.this, BACK_CAMERA);
previewFrameLayout.addView(mCameraPreview);
}
}
}, 250);
}
});
flashImageButton = (ImageButton) findViewById(R.id.flash);
flashImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Utils.scaleView(flashImageButton);
try {
Camera.Parameters parameters = mCamera.getParameters();
if (!isFlashEnabled) {
isFlashEnabled = true;
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
flashImageButton.setSelected(true);
} else {
isFlashEnabled = false;
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
flashImageButton.setSelected(false);
}
mCamera.setParameters(parameters);
} catch (Exception e) {
e.printStackTrace();
}
}
});
if (!isFlashAvailable) {
flashImageButton.setVisibility(View.GONE);
}
if (!isFrontCamera) {
switchCamera.setVisibility(View.GONE);
}
backImageButton = (ImageButton) findViewById(R.id.back);
backImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
private void hideIcons() {
switchCamera.setVisibility(View.GONE);
captureButton.setVisibility(View.GONE);
flashImageButton.setVisibility(View.GONE);
backImageButton.setVisibility(View.GONE);
}
private void showIcons() {
switchCamera.setVisibility(View.VISIBLE);
captureButton.setVisibility(View.VISIBLE);
flashImageButton.setVisibility(View.VISIBLE);
backImageButton.setVisibility(View.VISIBLE);
}
#Override
protected void onResume() {
super.onResume();
mCameraPreview = new CameraPreview(this, mCameraId);
previewFrameLayout.addView(mCameraPreview);
}
#Override
protected void onPause() {
super.onPause();
mCameraPreview.stop();
previewFrameLayout.removeView(mCameraPreview); // This is necessary.
mCameraPreview = null;
}
Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
final File pictureFile = new File(Utils.profilePicPath + String.valueOf(System.currentTimeMillis()) + ".jpg");
pictureFile.getParentFile().mkdirs();
Utils.deleteCapture();
if (pictureFile == null) {
return;
}
Thread thread = new Thread() {
#Override
public void run() {
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pictureFile.getPath(), bmOptions);
final int height = bmOptions.outHeight;
final int width = bmOptions.outWidth;
if (height > width) {
if (height / width < 1.5) {
Bitmap bitmap = Picasso.with(CameraNewActivity.this)
.load(pictureFile).resize((int) (height / 1.65), height).centerCrop().get();
if (mCameraId == FRONT_CAMERA) {
bitmap = flip(bitmap);
}
FileOutputStream out = new FileOutputStream(pictureFile.getPath());
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
thread.start();
}
};
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
protected List<Camera.Size> mPreviewSizeList;
protected List<Camera.Size> mPictureSizeList;
protected Camera.Size mPreviewSize;
protected Camera.Size mPictureSize;
private int mSurfaceChangedCallDepth = 0;
private int mCenterPosX = -1;
private int mCenterPosY = 0;
protected boolean mSurfaceChanged = false;
public CameraPreview(Activity activity, int cameraId) {
super(activity);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
if (Camera.getNumberOfCameras() > cameraId) {
mCameraId = cameraId;
} else {
mCameraId = 0;
}
mCamera = Camera.open(mCameraId);
Camera.Parameters cameraParams = mCamera.getParameters();
mPreviewSizeList = cameraParams.getSupportedPreviewSizes();
mPictureSizeList = cameraParams.getSupportedPictureSizes();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mSurfaceChangedCallDepth++;
mCamera.stopPreview();
Camera.Parameters cameraParams = mCamera.getParameters();
if (!mSurfaceChanged) {
Camera.Size previewSize = determinePreviewSize(width, height);
Camera.Size pictureSize = determinePictureSize(previewSize);
mPreviewSize = previewSize;
mPictureSize = pictureSize;
mSurfaceChanged = adjustSurfaceLayoutSize(previewSize, width, height);
if (mSurfaceChanged && (mSurfaceChangedCallDepth <= 1)) {
return;
}
}
if (mCameraId == BACK_CAMERA) {
cameraParams.setRotation(90);
} else {
cameraParams.setRotation(270);
}
mCamera.setDisplayOrientation(90);
cameraParams.set("orientation", "portrait");
cameraParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
cameraParams.setPictureSize(mPictureSize.width, mPictureSize.height);
mCamera.setParameters(cameraParams);
mSurfaceChanged = false;
try {
mCamera.startPreview();
} catch (Exception e) {
// Remove failed size
mPreviewSizeList.remove(mPreviewSize);
mPreviewSize = null;
// Reconfigure
if (mPreviewSizeList.size() > 0) { // prevent infinite loop
surfaceChanged(null, 0, width, height);
} else {
Utils.showToast(CameraNewActivity.this, "Can't start preview", Toast.LENGTH_LONG);
}
}
mSurfaceChangedCallDepth--;
}
protected Camera.Size determinePreviewSize(int reqWidth, int reqHeight) {
int reqPreviewWidth = reqHeight; // requested width in terms of camera hardware
int reqPreviewHeight = reqWidth; // requested height in terms of camera hardware
// Adjust surface size with the closest aspect-ratio
float reqRatio = ((float) reqPreviewWidth) / reqPreviewHeight;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
Camera.Size retSize = null;
for (Camera.Size size : mPreviewSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
return retSize;
}
protected Camera.Size determinePictureSize(Camera.Size previewSize) {
Camera.Size retSize = null;
for (Camera.Size size : mPictureSizeList) {
if (size.equals(previewSize)) {
return size;
}
}
// if the preview size is not supported as a picture size
float reqRatio = ((float) previewSize.width) / previewSize.height;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
for (Camera.Size size : mPictureSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
return retSize;
}
protected boolean adjustSurfaceLayoutSize(Camera.Size previewSize,
int availableWidth, int availableHeight) {
float tmpLayoutHeight = previewSize.width;
float tmpLayoutWidth = previewSize.height;
float factH, factW, fact;
factH = availableHeight / tmpLayoutHeight;
factW = availableWidth / tmpLayoutWidth;
if (factH < factW) {
fact = factH;
} else {
fact = factW;
}
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) this.getLayoutParams();
int layoutHeight = (int) (tmpLayoutHeight * fact);
int layoutWidth = (int) (tmpLayoutWidth * fact);
boolean layoutChanged;
if ((layoutWidth != this.getWidth()) || (layoutHeight != this.getHeight())) {
layoutParams.height = layoutHeight;
layoutParams.width = layoutWidth;
if (mCenterPosX >= 0) {
layoutParams.topMargin = mCenterPosY - (layoutHeight / 2);
layoutParams.leftMargin = mCenterPosX - (layoutWidth / 2);
}
this.setLayoutParams(layoutParams); // this will trigger another surfaceChanged invocation.
layoutChanged = true;
} else {
layoutChanged = false;
}
return layoutChanged;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
stop();
}
public void stop() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
}
public Bitmap flip(Bitmap bitmap) {
Matrix mtx = new Matrix();
mtx.preScale(-1, 1);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), mtx, true);
}
}
I am trying to create custom camera preview logic that actually works properly, for all scenarios:
any device: phone, tablet
any camera: front-facing, rear-facing
android.hardware.Camera
My android:minSdkVersion is 14 and android:targetSdkVersion is 21.
I have implemented custom camera preview class to set display orientation for camera preview and working very well for all devices without only Nexus devices. Nexus devices have I think default 180 orientation.
While I am starting my camera in Nexus devices it is showing inverted. To overcome with i have checked with Build.MANUFACTURER & Build.MODEL to identify the device and set orientation according to it.
if (Build.MODEL.equals("Nexus 6P") && Build.MANUFACTURER.equals("Huawei")) mCamera.setDisplayOrientation(90);
else mCamera.setDisplayOrientation(270);
But it is not working. So can anyone have idea to overcome with this and recommended way !! Advance help would be appreciated !!
As far as I know this problem doesn't occur on Nexus 5. I had to deal with it on a Nexus 5X and I lost some time trying(Click here to see why). As a big note, I can't guarantee that it's the best solution, but it fixed all the problems I had. To solve it I did something like this:
I created a class CameraPreview extends SurfaceView only to encapsulate all the preview initialisation in one place. Here is the constructor for that class:
public CameraPreview(Context context, int screenRotation, Camera camera) {
super(context);
mCamera = camera;
mScreenRotation = screenRotation;
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
}
To create the preview I used this: mPreview = new CameraPreview(getContext(), screenRotation, mCamera);, where screenRotation is int screenRotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
When the surfaceCreated callback is called:
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
setCameraDisplayOrientation(mScreenRotation, 0, mCamera);
Here,0 comes from the cameraId (it might be different if you're using the front facing camera). And here is all the magic:
public void setCameraDisplayOrientation(int screenRotation, int cameraId, Camera camera) {
int rotation = getRotationAngle(screenRotation, cameraId);
camera.setDisplayOrientation(rotation);
}
public static int getRotationAngle(int screenRotation, int cameraId) {
Camera.CameraInfo info = new Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int degrees = 0;
switch (screenRotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
return result;
}
I hope that this will fix the problem, but before starting to write it, make sure that you read the link I provided to see why the problem takes place. Hope this will fix it for you too.
To initiate in activity :
CameraPreviewNew mPreview = new ResizableCameraPreview(this, cameraId, CameraPreviewNew.LayoutMode.NoBlank, false, screenHeight, screenWidth); // cameraId for front or rear
LinearLayout.LayoutParams previewLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
frameCamera.addView(mPreview, 0, previewLayoutParams);
CameraPreviewNew.java
public class CameraPreviewNew extends SurfaceView implements SurfaceHolder.Callback {
private static boolean DEBUGGING = false;
private static final String LOG_TAG = "CameraPreviewSample";
private static final String CAMERA_PARAM_ORIENTATION = "orientation";
private static final String CAMERA_PARAM_LANDSCAPE = "landscape";
private static final String CAMERA_PARAM_PORTRAIT = "portrait";
protected Activity mActivity;
private SurfaceHolder mHolder;
protected Camera mCamera;
protected List<Camera.Size> mPreviewSizeList;
protected List<Camera.Size> mPictureSizeList;
protected Camera.Size mPreviewSize;
protected Camera.Size mPictureSize;
private int mSurfaceChangedCallDepth = 0;
private int mCameraId;
private LayoutMode mLayoutMode;
private int mCenterPosX = -1;
private int mCenterPosY;
private int screenHeight, screenWidth;
PreviewReadyCallback mPreviewReadyCallback = null;
public enum LayoutMode {
FitToParent, // Scale to the size that no side is larger than the parent
NoBlank // Scale to the size that no side is smaller than the parent
}
public interface PreviewReadyCallback {
void onPreviewReady();
}
/**
* State flag: true when surface's layout size is set and surfaceChanged()
* process has not been completed.
*/
protected boolean mSurfaceConfiguring = false;
public CameraPreviewNew(Activity activity, int cameraId, LayoutMode mode, int screenHeight, int screenWidth) {
super(activity); // Always necessary
mActivity = activity;
mLayoutMode = mode;
this.screenHeight = screenHeight;
this.screenWidth = screenWidth;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// mHolder.setFixedSize(fixWidth, fixHeight);
// FileLog.v("Camera ID ::::::::::: " + cameraId);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
if (Camera.getNumberOfCameras() > cameraId) {
mCameraId = cameraId;
} else {
mCameraId = 0;
}
} else {
mCameraId = 0;
}
// FileLog.d("Camera ID ::::::::::: " + cameraId);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
mCamera = Camera.open(mCameraId);
} else {
mCamera = Camera.open();
}
Camera.Parameters cameraParams = mCamera.getParameters();
mPreviewSizeList = cameraParams.getSupportedPreviewSizes();
mPictureSizeList = cameraParams.getSupportedPictureSizes();
// FileLog.d("Preview Size ID ::::::::::: " + mPreviewSizeList);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mSurfaceChangedCallDepth++;
doSurfaceChanged(width, height);
mSurfaceChangedCallDepth--;
}
public void doSurfaceChanged(int width, int height) {
mCamera.stopPreview();
Camera.Parameters cameraParams = mCamera.getParameters();
boolean portrait = isPortrait();
// The code in this if-statement is prevented from executed again when surfaceChanged is
// called again due to the change of the layout size in this if-statement.
if (!mSurfaceConfiguring) {
Camera.Size previewSize = determinePreviewSize(portrait, width, height);
Camera.Size pictureSize = determinePictureSize(previewSize);
if (DEBUGGING) { Log.v(LOG_TAG, "Desired Preview Size - w: " + width + ", h: " + height); }
mPreviewSize = previewSize;
mPictureSize = pictureSize;
mSurfaceConfiguring = adjustSurfaceLayoutSize(previewSize, portrait, width, height);
// Continue executing this method if this method is called recursively.
// Recursive call of surfaceChanged is very special case, which is a path from
// the catch clause at the end of this method.
// The later part of this method should be executed as well in the recursive
// invocation of this method, because the layout change made in this recursive
// call will not trigger another invocation of this method.
if (mSurfaceConfiguring && (mSurfaceChangedCallDepth <= 1)) {
return;
}
}
configureCameraParameters(cameraParams, portrait);
mSurfaceConfiguring = false;
try {
mCamera.startPreview();
} catch (Exception e) {
Log.w(LOG_TAG, "Failed to start preview: " + e.getMessage());
// Remove failed size
mPreviewSizeList.remove(mPreviewSize);
mPreviewSize = null;
// Reconfigure
if (mPreviewSizeList.size() > 0) { // prevent infinite loop
surfaceChanged(null, 0, width, height);
} else {
Log.w(LOG_TAG, "Gave up starting preview");
}
}
if (null != mPreviewReadyCallback) {
mPreviewReadyCallback.onPreviewReady();
}
}
/**
* #param portrait
* #param reqWidth must be the value of the parameter passed in surfaceChanged
* #param reqHeight must be the value of the parameter passed in surfaceChanged
* #return Camera.Size object that is an element of the list returned from Camera.Parameters.getSupportedPreviewSizes.
*/
protected Camera.Size determinePreviewSize(boolean portrait, int reqWidth, int reqHeight) {
// Meaning of width and height is switched for preview when portrait,
// while it is the same as user's view for surface and metrics.
// That is, width must always be larger than height for setPreviewSize.
int reqPreviewWidth; // requested width in terms of camera hardware
int reqPreviewHeight; // requested height in terms of camera hardware
if (portrait) {
reqPreviewWidth = reqHeight;
reqPreviewHeight = reqWidth;
} else {
reqPreviewWidth = reqWidth;
reqPreviewHeight = reqHeight;
}
if (DEBUGGING) {
Log.v(LOG_TAG, "Listing all supported preview sizes");
for (Camera.Size size : mPreviewSizeList) {
Log.v(LOG_TAG, " w: " + size.width + ", h: " + size.height);
}
Log.v(LOG_TAG, "Listing all supported picture sizes");
for (Camera.Size size : mPictureSizeList) {
Log.v(LOG_TAG, " w: " + size.width + ", h: " + size.height);
}
}
// Adjust surface size with the closest aspect-ratio
float reqRatio = ((float) reqPreviewWidth) / reqPreviewHeight;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
Camera.Size retSize = null;
for (Camera.Size size : mPreviewSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
retSize = mPreviewSizeList.get(0);
return retSize;
}
protected Camera.Size determinePictureSize(Camera.Size previewSize) {
Camera.Size retSize = null;
for (Camera.Size size : mPictureSizeList) {
if (size.equals(previewSize)) {
return size;
}
}
if (DEBUGGING) { Log.v(LOG_TAG, "Same picture size not found."); }
// if the preview size is not supported as a picture size
float reqRatio = ((float) previewSize.width) / previewSize.height;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
for (Camera.Size size : mPictureSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
retSize = mPictureSizeList.get(0);
return retSize;
}
protected boolean adjustSurfaceLayoutSize(Camera.Size previewSize, boolean portrait,
int availableWidth, int availableHeight) {
float tmpLayoutHeight, tmpLayoutWidth;
if (portrait) {
tmpLayoutHeight = previewSize.width;
tmpLayoutWidth = previewSize.height;
} else {
tmpLayoutHeight = previewSize.height;
tmpLayoutWidth = previewSize.width;
}
float factH, factW, fact;
factH = availableHeight / tmpLayoutHeight;
factW = availableWidth / tmpLayoutWidth;
if (mLayoutMode == LayoutMode.FitToParent) {
// Select smaller factor, because the surface cannot be set to the size larger than display metrics.
if (factH < factW) {
fact = factH;
} else {
fact = factW;
}
} else {
if (factH < factW) {
fact = factW;
} else {
fact = factH;
}
}
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)this.getLayoutParams();
int layoutHeight = (int) (tmpLayoutHeight * fact);
int layoutWidth = (int) (tmpLayoutWidth * fact);
if (DEBUGGING) {
Log.v(LOG_TAG, "Preview Layout Size - w: " + layoutWidth + ", h: " + layoutHeight);
Log.v(LOG_TAG, "Scale factor: " + fact);
}
boolean layoutChanged;
if ((layoutWidth != this.getWidth()) || (layoutHeight != this.getHeight())) {
int diffHeight = (screenHeight - layoutHeight) / 2;
layoutParams.height = layoutHeight + diffHeight;
int diffWidth = (screenWidth - layoutWidth) / 2;
layoutParams.width = layoutWidth + diffWidth;
if (mCenterPosX >= 0) {
layoutParams.topMargin = mCenterPosY - (layoutHeight / 2);
layoutParams.leftMargin = mCenterPosX - (layoutWidth / 2);
}
this.setLayoutParams(layoutParams); // this will trigger another surfaceChanged invocation.
layoutChanged = true;
} else {
layoutChanged = false;
}
return layoutChanged;
}
/**
* #param x X coordinate of center position on the screen. Set to negative value to unset.
* #param y Y coordinate of center position on the screen.
*/
public void setCenterPosition(int x, int y) {
mCenterPosX = x;
mCenterPosY = y;
}
protected void configureCameraParameters(Camera.Parameters cameraParams, boolean portrait) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { // for 2.1 and before
if (portrait) {
cameraParams.set(CAMERA_PARAM_ORIENTATION, CAMERA_PARAM_PORTRAIT);
} else {
cameraParams.set(CAMERA_PARAM_ORIENTATION, CAMERA_PARAM_LANDSCAPE);
}
} else { // for 2.2 and later
int angle;
Display display = mActivity.getWindowManager().getDefaultDisplay();
switch (display.getRotation()) {
case Surface.ROTATION_0: // This is display orientation
angle = 90; // This is camera orientation
break;
case Surface.ROTATION_90:
angle = 0;
break;
case Surface.ROTATION_180:
angle = 270;
break;
case Surface.ROTATION_270:
angle = 180;
break;
default:
angle = 90;
break;
}
Log.v(LOG_TAG, "angle: " + angle);
mCamera.setDisplayOrientation(angle);
}
cameraParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
cameraParams.setPictureSize(mPictureSize.width, mPictureSize.height);
cameraParams.setZoom(0);
// if (cameraParams.isZoomSupported()) {
final int maxZoomLevel = cameraParams.getMaxZoom();
Log.e("max ZOOM ", "is " + maxZoomLevel);
// }
// cameraParams.setPreviewSize(fixWidth, fixHeight);
// cameraParams.setPictureSize(fixWidth, fixHeight);
if (DEBUGGING) {
Log.v(LOG_TAG, "Preview Actual Size - w: " + mPreviewSize.width + ", h: " + mPreviewSize.height);
Log.v(LOG_TAG, "Picture Actual Size - w: " + mPictureSize.width + ", h: " + mPictureSize.height);
}
mCamera.setParameters(cameraParams);
}
#SuppressWarnings("unused")
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.2;
double targetRatio = (double) w / h;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (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)
continue;
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;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
stop();
}
public void stop() {
try {
if (null == mCamera) {
return;
}
if(mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}catch (Exception e){
e.printStackTrace();
}
}
public boolean isPortrait() {
return (mActivity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
}
public void setOneShotPreviewCallback(PreviewCallback callback) {
if (null == mCamera) {
return;
}
mCamera.setOneShotPreviewCallback(callback);
}
public void setPreviewCallback(PreviewCallback callback) {
if (null == mCamera) {
return;
}
mCamera.setPreviewCallback(callback);
}
public Camera.Size getPreviewSize() {
return mPreviewSize;
}
public void setOnPreviewReady(PreviewReadyCallback cb) {
mPreviewReadyCallback = cb;
}
public Camera getPreviewCamera() {
return mCamera;
}
}
ResizableCameraPreview.java
public class ResizableCameraPreview extends CameraPreviewNew {
private static boolean DEBUGGING = false;
private static final String LOG_TAG = "ResizableCameraPreviewSample";
/**
* #param activity
* #param addReversedSizes is set to true to add reversed values of supported preview-sizes to the list.
*/
public ResizableCameraPreview(Activity activity, int cameraId, LayoutMode mode, boolean addReversedSizes, int screenHeight, int screenWidth) {
super(activity, cameraId, mode, screenHeight, screenWidth);
if (addReversedSizes) {
List<Camera.Size> sizes = mPreviewSizeList;
int length = sizes.size();
for (int i = 0; i < length; i++) {
Camera.Size size = sizes.get(i);
Camera.Size revSize = mCamera.new Size(size.height, size.width);
sizes.add(revSize);
}
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mCamera.stopPreview();
Camera.Parameters cameraParams = mCamera.getParameters();
boolean portrait = isPortrait();
if (!mSurfaceConfiguring) {
Camera.Size previewSize = determinePreviewSize(portrait, width, height);
Camera.Size pictureSize = determinePictureSize(previewSize);
Log.v(LOG_TAG, "Desired Preview Size - w: " + width + ", h: " + height);
mPreviewSize = previewSize;
mPictureSize = pictureSize;
mSurfaceConfiguring = adjustSurfaceLayoutSize(previewSize, portrait, width, height);
if (mSurfaceConfiguring) {
return;
}
}
configureCameraParameters(cameraParams, portrait);
mSurfaceConfiguring = false;
try {
mCamera.startPreview();
} catch (Exception e) {
Log.w(LOG_TAG, "Failed to start preview: " + e.getMessage());
}
}
/**
*
* #param index selects preview size from the list returned by CameraPreview.getSupportedPreivewSizes().
* #param width is the width of the available area for this view
* #param height is the height of the available area for this view
*/
public void setPreviewSize(int index, int width, int height) {
mCamera.stopPreview();
Camera.Parameters cameraParams = mCamera.getParameters();
boolean portrait = isPortrait();
Camera.Size previewSize = mPreviewSizeList.get(index);
Camera.Size pictureSize = determinePictureSize(previewSize);
if (DEBUGGING) { Log.v(LOG_TAG, "Requested Preview Size - w: " + previewSize.width + ", h: " + previewSize.height); }
mPreviewSize = previewSize;
mPictureSize = pictureSize;
boolean layoutChanged = adjustSurfaceLayoutSize(previewSize, portrait, width, height);
if (layoutChanged) {
mSurfaceConfiguring = true;
return;
}
configureCameraParameters(cameraParams, portrait);
try {
mCamera.startPreview();
} catch (Exception e) {
}
mSurfaceConfiguring = false;
}
public List<Camera.Size> getSupportedPreivewSizes() {
return mPreviewSizeList;
}
}
Xml file :
<FrameLayout
android:id="#+id/frm"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:id="#+id/frameCamera"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
</FrameLayout>
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Please tell me how to create a square size camera in my android application as in instagram? I was looking for a solution for a very long time, but I couldn't find it.
You can not create an square size camera its totally depends upon the device.
Basically every device have their own camera sizes you can get the
list of all the device's size and then set your prefer one...!
Here is a camera preview class which auto set the good size to the camera view,
import java.io.IOException;
import java.util.List;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.RelativeLayout;
import android.widget.Toast;
/**
* This class assumes the parent layout is RelativeLayout.LayoutParams.
*/
#SuppressWarnings("deprecation")
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static boolean DEBUGGING = true;
private static final String LOG_TAG = "CameraPreviewSample";
private static final String CAMERA_PARAM_ORIENTATION = "orientation";
private static final String CAMERA_PARAM_LANDSCAPE = "landscape";
private static final String CAMERA_PARAM_PORTRAIT = "portrait";
protected CameraActivity mActivity;
private SurfaceHolder mHolder;
protected Camera mCamera;
protected List<Camera.Size> mPreviewSizeList;
protected List<Camera.Size> mPictureSizeList;
protected Camera.Size mPreviewSize;
protected Camera.Size mPictureSize;
private int mSurfaceChangedCallDepth = 0;
private int mCameraId;
private LayoutMode mLayoutMode;
private int mCenterPosX = -1;
private int mCenterPosY;
public static boolean isSafeForTakeImage = false;
PreviewReadyCallback mPreviewReadyCallback = null;
public static enum LayoutMode
{
FitToParent, // Scale to the size that no side is larger than the parent
NoBlank // Scale to the size that no side is smaller than the parent
};
public interface PreviewReadyCallback {
public void onPreviewReady();
}
/**
* State flag: true when surface's layout size is set and surfaceChanged()
* process has not been completed.
*/
protected boolean mSurfaceConfiguring = false;
public CameraPreview(CameraActivity activity, int cameraId, LayoutMode mode) {
super(activity); // Always necessary
mActivity = activity;
mLayoutMode = mode;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
if (Camera.getNumberOfCameras() > cameraId) {
mCameraId = cameraId;
} else {
mCameraId = 0;
}
} else {
mCameraId = 0;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
mCamera = Camera.open(mCameraId);
} else {
mCamera = Camera.open();
}
Camera.Parameters cameraParams = mCamera.getParameters();
mPreviewSizeList = cameraParams.getSupportedPreviewSizes();
mPictureSizeList = cameraParams.getSupportedPictureSizes();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try
{
isSafeForTakeImage = true;
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mSurfaceChangedCallDepth++;
doSurfaceChanged(width, height);
mSurfaceChangedCallDepth--;
}
private void doSurfaceChanged(int width, int height)
{
isSafeForTakeImage = false;
mCamera.stopPreview();
Camera.Parameters cameraParams = mCamera.getParameters();
// cameraParams.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
if(cameraParams.getSupportedFocusModes() != null
&& cameraParams.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
{
cameraParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
cameraParams.setRotation(90);
boolean portrait = isPortrait();
// The code in this if-statement is prevented from executed again when surfaceChanged is
// called again due to the change of the layout size in this if-statement.
if (!mSurfaceConfiguring) {
Camera.Size previewSize = determinePreviewSize(portrait, width, height);
Camera.Size pictureSize = determinePictureSize(previewSize);
if (DEBUGGING) { Log.v(LOG_TAG, "Desired Preview Size - w: " + width + ", h: " + height); }
mPreviewSize = previewSize;
mPictureSize = pictureSize;
// mSurfaceConfiguring = adjustSurfaceLayoutSize(previewSize, portrait, width, height);
// Continue executing this method if this method is called recursively.
// Recursive call of surfaceChanged is very special case, which is a path from
// the catch clause at the end of this method.
// The later part of this method should be executed as well in the recursive
// invocation of this method, because the layout change made in this recursive
// call will not trigger another invocation of this method.
if (mSurfaceConfiguring && (mSurfaceChangedCallDepth <= 1)) {
return;
}
}
configureCameraParameters(cameraParams, portrait);
mSurfaceConfiguring = false;
try {
mCamera.startPreview();
isSafeForTakeImage = true;
} catch (Exception e) {
Log.w(LOG_TAG, "Failed to start preview: " + e.getMessage());
// Remove failed size
mPreviewSizeList.remove(mPreviewSize);
mPreviewSize = null;
// Reconfigure
if (mPreviewSizeList.size() > 0) { // prevent infinite loop
surfaceChanged(null, 0, width, height);
} else {
Toast.makeText(mActivity, "Can't start preview", Toast.LENGTH_LONG).show();
Log.w(LOG_TAG, "Gave up starting preview");
}
}
if (null != mPreviewReadyCallback) {
mPreviewReadyCallback.onPreviewReady();
}
//TODO
mActivity.setMyCamera(mCamera);
}
/**
* #param cameraParams
* #param portrait
* #param reqWidth must be the value of the parameter passed in surfaceChanged
* #param reqHeight must be the value of the parameter passed in surfaceChanged
* #return Camera.Size object that is an element of the list returned from Camera.Parameters.getSupportedPreviewSizes.
*/
protected Camera.Size determinePreviewSize(boolean portrait, int reqWidth, int reqHeight) {
// Meaning of width and height is switched for preview when portrait,
// while it is the same as user's view for surface and metrics.
// That is, width must always be larger than height for setPreviewSize.
int reqPreviewWidth; // requested width in terms of camera hardware
int reqPreviewHeight; // requested height in terms of camera hardware
if (portrait) {
reqPreviewWidth = reqHeight;
reqPreviewHeight = reqWidth;
} else {
reqPreviewWidth = reqWidth;
reqPreviewHeight = reqHeight;
}
if (DEBUGGING) {
Log.v(LOG_TAG, "Listing all supported preview sizes");
for (Camera.Size size : mPreviewSizeList) {
Log.v(LOG_TAG, " w: " + size.width + ", h: " + size.height);
}
Log.v(LOG_TAG, "Listing all supported picture sizes");
for (Camera.Size size : mPictureSizeList) {
Log.v(LOG_TAG, " w: " + size.width + ", h: " + size.height);
}
}
// Adjust surface size with the closest aspect-ratio
float reqRatio = ((float) reqPreviewWidth) / reqPreviewHeight;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
Camera.Size retSize = null;
for (Camera.Size size : mPreviewSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
return retSize;
}
protected Camera.Size determinePictureSize(Camera.Size previewSize) {
Camera.Size retSize = null;
for (Camera.Size size : mPictureSizeList) {
if (size.equals(previewSize)) {
return size;
}
}
if (DEBUGGING) { Log.v(LOG_TAG, "Same picture size not found."); }
// if the preview size is not supported as a picture size
float reqRatio = ((float) previewSize.width) / previewSize.height;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
for (Camera.Size size : mPictureSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
return retSize;
}
protected boolean adjustSurfaceLayoutSize(Camera.Size previewSize, boolean portrait,
int availableWidth, int availableHeight) {
float tmpLayoutHeight, tmpLayoutWidth;
if (portrait) {
tmpLayoutHeight = previewSize.width;
tmpLayoutWidth = previewSize.height;
} else {
tmpLayoutHeight = previewSize.height;
tmpLayoutWidth = previewSize.width;
}
float factH, factW, fact;
factH = availableHeight / tmpLayoutHeight;
factW = availableWidth / tmpLayoutWidth;
if (mLayoutMode == LayoutMode.FitToParent) {
// Select smaller factor, because the surface cannot be set to the size larger than display metrics.
if (factH < factW) {
fact = factH;
} else {
fact = factW;
}
} else {
if (factH < factW) {
fact = factW;
} else {
fact = factH;
}
}
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)this.getLayoutParams();
int layoutHeight = (int) (tmpLayoutHeight * fact);
int layoutWidth = (int) (tmpLayoutWidth * fact);
if (DEBUGGING) {
Log.v(LOG_TAG, "Preview Layout Size - w: " + layoutWidth + ", h: " + layoutHeight);
Log.v(LOG_TAG, "Scale factor: " + fact);
}
boolean layoutChanged;
if ((layoutWidth != this.getWidth()) || (layoutHeight != this.getHeight())) {
layoutParams.height = layoutHeight;
layoutParams.width = layoutWidth;
if (mCenterPosX >= 0) {
layoutParams.topMargin = mCenterPosY - (layoutHeight / 2);
layoutParams.leftMargin = mCenterPosX - (layoutWidth / 2);
}
this.setLayoutParams(layoutParams); // this will trigger another surfaceChanged invocation.
layoutChanged = true;
} else {
layoutChanged = false;
}
return layoutChanged;
}
/**
* #param x X coordinate of center position on the screen. Set to negative value to unset.
* #param y Y coordinate of center position on the screen.
*/
public void setCenterPosition(int x, int y) {
mCenterPosX = x;
mCenterPosY = y;
}
protected void configureCameraParameters(Camera.Parameters cameraParams, boolean portrait) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { // for 2.1 and before
if (portrait)
{
cameraParams.set(CAMERA_PARAM_ORIENTATION, CAMERA_PARAM_PORTRAIT);
}
else
{
cameraParams.set(CAMERA_PARAM_ORIENTATION, CAMERA_PARAM_LANDSCAPE);
}
} else { // for 2.2 and later
int angle;
Display display = mActivity.getWindowManager().getDefaultDisplay();
switch (display.getRotation()) {
case Surface.ROTATION_0: // This is display orientation
angle = 90; // This is camera orientation
break;
case Surface.ROTATION_90:
angle = 0;
break;
case Surface.ROTATION_180:
angle = 270;
break;
case Surface.ROTATION_270:
angle = 180;
break;
default:
angle = 90;
break;
}
Log.v(LOG_TAG, "angle: " + angle);
mCamera.setDisplayOrientation(angle);
}
cameraParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
cameraParams.setPictureSize(mPictureSize.width, mPictureSize.height);
if (DEBUGGING) {
Log.v(LOG_TAG, "Preview Actual Size - w: " + mPreviewSize.width + ", h: " + mPreviewSize.height);
Log.v(LOG_TAG, "Picture Actual Size - w: " + mPictureSize.width + ", h: " + mPictureSize.height);
}
mCamera.setParameters(cameraParams);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
stop();
isSafeForTakeImage = false;
}
public void stop() {
if (null == mCamera) {
return;
}
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
public boolean isPortrait() {
return (mActivity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
}
public void setOneShotPreviewCallback(PreviewCallback callback) {
if (null == mCamera) {
return;
}
mCamera.setOneShotPreviewCallback(callback);
}
public void setPreviewCallback(PreviewCallback callback) {
if (null == mCamera) {
return;
}
mCamera.setPreviewCallback(callback);
}
public Camera.Size getPreviewSize() {
return mPreviewSize;
}
public void setOnPreviewReady(PreviewReadyCallback cb) {
mPreviewReadyCallback = cb;
}
}
You need the below permissions in your AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-feature
android:name="android.hardware.camera.autofocus"
android:required="false" />
The above class assume, you are using relative layout,
In your activity put this code in your onResume() method,
surfaceview = new CameraPreview(this, 0, CameraPreview.LayoutMode.FitToParent);
LayoutParams previewLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
previewLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
relativeLayout.addView(surfaceview, 0, previewLayoutParams);
Add below lines in your onPause() method
try{
relativeLayout.removeView(surfaceview);
}catch(Exception exception){
}
Until now I have a full working code that plugs in a camera to see the preview of the front camera.
What I'm trying to do now is to get that camera working inside a Fragment.
Full code:
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_main);
getFragmentManager().beginTransaction().add(R.id.mainLayout, new CameraExtractionFragment()).commit();
}
}
CameraExtractionFragment.java
public class CameraExtractionFragment extends Fragment {
private CameraExtraction mCameraExtraction;
Camera mCamera;
int mNumberOfCameras;
int cameraId;
int rotation;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCameraExtraction = new CameraExtraction(
this.getActivity().getBaseContext(),
this.getActivity().getWindowManager().getDefaultDisplay().getRotation()
);
// Find the total number of cameras available
mNumberOfCameras = Camera.getNumberOfCameras();
// Find the ID of the rear-facing ("default") camera
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < mNumberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
cameraId = i;
}
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return mCameraExtraction;
}
#Override
public void onResume() {
super.onResume();
// Use mCurrentCamera to select the camera desired to safely restore
// the fragment after the camera has been changed
mCamera = Camera.open(cameraId);
mCameraExtraction.setCamera(mCamera);
}
#Override
public void onPause() {
super.onPause();
if (mCamera != null)
{
mCamera.release();
}
}
// Modo en el que se pinta la cámara: encajada por dentro o saliendo los bordes por fuera.
public enum CameraViewMode {
/**
* Inner mode
*/
Inner,
/**
* Outer mode
*/
Outer
}
}
CameraExtraction.java
public class CameraExtraction extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "CameraExtraction";
Camera mCamera;
SurfaceHolder mHolder;
SurfaceView mSurfaceView;
int mNumberOfCameras;
int cameraId;
Rect desiredSize;
CameraViewMode cameraViewMode;
boolean mSurfaceCreated = false;
List<Size> mSupportedPreviewSizes;
int rotation;
Size mPreviewSize;
public CameraExtraction(Context context, int rotation) {
super(context);
this.rotation = rotation;
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
// Install a SurfaceHolder.Callback so we get notified when the
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
cameraViewMode = CameraViewMode.Inner;
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
if (mSurfaceCreated) requestLayout();
}
}
public void switchCamera(Camera camera) {
setCamera(camera);
try {
camera.setPreviewDisplay(mHolder);
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
#SuppressLint("DrawAllocation")
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mSurfaceView == null ||mSurfaceView.getHolder() == null) return;
if (mSurfaceView.getHolder().getSurface() == null) {
// preview surface does not exist
return;
}
final int width = resolveSize(getSuggestedMinimumWidth(),
widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(),
heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getNearestPreviewSize(mCamera.new Size(widthMeasureSpec,heightMeasureSpec));
}
if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}
// Center the child SurfaceView within the parent.
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height
/ previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width
/ previewWidth;
child.layout(0, (height - scaledChildHeight) / 2, width,
(height + scaledChildHeight) / 2);
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open(cameraId);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
if (mSurfaceView == null || mSurfaceView.getHolder() == null) return;
if (mSurfaceView.getHolder().getSurface() == null) {
// preview surface does not exist
return;
}
// set preview size and make any resize, rotate or
// reformatting changes here
Camera.Parameters param = mCamera.getParameters();
Point previewSize = new Point(640,480);
Camera.Size size = getNearestPreviewSize(mCamera.new Size(previewSize.x,previewSize.y));
param.setPreviewSize(size.width, size.height);
mCamera.setParameters(param);
rotation = setCameraDisplayOrientation(cameraId, mCamera);
// start preview with new settings
try {
mCamera.setPreviewCallback(new Camera.PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
// TODO Auto-generated method stub
}
});
mCamera.setPreviewDisplay(mSurfaceView.getHolder());
mCamera.startPreview();
} catch (Exception e) {
Log.d("AndroidControlSurfaceView",
"Error starting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null)
{
mCamera.stopPreview();
mCamera.release();
}
}
protected Rect getCameraViewSizeCompensated(Camera.Size cameraPreviewSize, Point hostViewSize) {
Rect toReturn=null;
float ratioWidth = hostViewSize.x / (float)cameraPreviewSize.width;
float ratioHeight = hostViewSize.y / (float)cameraPreviewSize.height;
switch (cameraViewMode){
case Inner:
if (ratioWidth < ratioHeight) {
int newHeight = (int)(cameraPreviewSize.height*ratioWidth);
int y = (hostViewSize.y - newHeight) / 2;
toReturn = new Rect(0, y, hostViewSize.x, y+newHeight);
} else {
int newWidth = (int)(cameraPreviewSize.width*ratioHeight);
int x = (hostViewSize.x - newWidth) / 2;
toReturn = new Rect(x, 0, x+newWidth,hostViewSize.y);
}
break;
case Outer:
if (ratioWidth < ratioHeight) {
int newWidth = (int)(cameraPreviewSize.width*ratioHeight);
int x = (hostViewSize.x - newWidth) / 2;
toReturn = new Rect(x, 0, x+newWidth,hostViewSize.y);
} else {
int newHeight = (int)(cameraPreviewSize.height*ratioWidth);
int y = (hostViewSize.y - newHeight) / 2;
toReturn = new Rect(0, y, hostViewSize.x, y+newHeight);
}
break;
}
return toReturn;
}
private Camera.Size getNearestPreviewSize(Camera.Size size) {
List<Camera.Size> availableSizes = mCamera.getParameters().getSupportedPreviewSizes();
if (availableSizes == null || availableSizes.size() <= 0) return null;
Camera.Size toReturn = availableSizes.get(0);
int distance = Math.abs(size.width*size.height - toReturn.width*toReturn.height);
for (int a=1; a<availableSizes.size(); a++) {
int temp = Math.abs(size.width*size.height - availableSizes.get(a).width*availableSizes.get(a).height);
if (temp < distance) {
distance = temp;
toReturn = availableSizes.get(a);
}
}
return toReturn;
}
public int setCameraDisplayOrientation(int cameraId, android.hardware.Camera camera) {
CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
return result/90;
}
}
But when you run the application, no image is being showed in my device. Only a white screen. Note that, as I mentioned the camera is working in an activity not containing fragments.
So, why the main activity is shown with a white screen?
PS: Here you can download my code and test it.
At first - use FrameLayout for your camera preview.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
The second - no need to open camera two times. Your surfaceCreated method.
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
mCamera.setPreviewCallback(new Camera.PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
}
});
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
The third - no need to release camera two times. You did it in Fragment, just remove it from surfaceDestroyed.
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null)
{
// mCamera.stopPreview();
// mCamera.release();
}
}
And in your fragment.
#Override
public void onPause() {
super.onPause();
if (mCamera != null)
{
mCamera.stopPreview();
mCamera.release();
}
}
And you will see your camera preview in a fragmentas I see. Good luck!
It seems you have attribute cameraId in CameraExtractionFragment and CameraExtraction, but this is assigned a value only in CameraExtractionFragment.
You should remove CameraExtraction.cameraId and use CameraExtractionFragment.cameraId instead.