Camera lags when orientation is changed - android

I am trying to create a camera preview using SurfaceView and it mostly works fine. I initialize the camera on onSurfaceCreated method and destroy it on onSurfaceDestroyed. Why are the above methods being called when the orientation of the device changes. Following is the surface view code.
#Override
public void surfaceCreated(SurfaceHolder holder) {
// Initialize the camera
initCamera();
Log.d("tags", "Camera Started!");
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (camera != null) {
camera.stopPreview();
camera.release();
}
Log.d("tags", "Camera destroyed!");
}
public void initCamera() {
if (camera == null) {
camera = Camera.open(); // Get's the first camera
}
try {
camera.setPreviewDisplay(sfHolder);
} catch (IOException err) {
err.printStackTrace();
}
// Set camera orientation
Activity activity = (Activity)this.getContext();
this.setCameraDisplayOrientation(activity);
camera.startPreview();
}
private void setCameraDisplayOrientation(Activity activity) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = 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;
}
Log.d("tag", "Result -- " + result);
boolean camNull = camera == null;
Log.d("tag", String.valueOf(camNull));
camera.setDisplayOrientation(result);
When I launch the application on my device, the preview starts as expected but when I change the orientation from portrait to landscape and vice versa, the preview hangs for a few seconds and the new preview is shown with the changed orientation.
According to the logs surface is being destroyed and created again when orientation changes and hence the camera is being re-initialized everytime orientation changes. How can I overcome this ? Am I doing anything wrong here ?

Related

Front camera brightness get very low when start recording in custom camera

I'm working in a custom video recorder which contain both front and back camera. When i start recording in back camera no problem, when i start recording in front camera brightness of the camera reduced.
i have camera switch button to change front and back camera
int currentCameraId;
reverseCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCamera.stopPreview();
mCamera.release();
if (currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
} else {
currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
mCamera = Camera.open(currentCameraId);
setCameraDisplayOrientation(UnlVideoActivity.this, currentCameraId, mCamera);
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
}
});
public void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
params.setRotation(rotation);
switch (rotation) {
case Surface.ROTATION_0:
Toast.makeText(UnlVideoActivity.this, "LAND", Toast.LENGTH_SHORT).show();
degrees = 0;
break;
case Surface.ROTATION_90:
Toast.makeText(UnlVideoActivity.this, "PORT", Toast.LENGTH_SHORT).show();
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);
camera.startPreview();
}
by this way i switch the front camera when i start recoring the brightness came to low.
code for recording
private boolean prepareMediaRecorder() {
mCamera = getCameraInstance();
mediaRecorder = new MediaRecorder();
mediaRecorder.setOrientationHint(orientationHint);
mCamera.unlock();
mediaRecorder.setPreviewDisplay(mHolder.getSurface());
mediaRecorder.setCamera(mCamera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
mediaRecorder.setOutputFile("/sdcard/myvideo.mp4");
mediaRecorder.setMaxDuration(60000); // Set max duration 60 sec.
mediaRecorder.setMaxFileSize(5000000); // Set max file size 5M
mediaRecorder.setPreviewDisplay(mCameraSurfaceView.getHolder().getSurface());
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
releaseMediaRecorder();
return false;
} catch (IOException e) {
releaseMediaRecorder();
return false;
}
return true;
}
You should try manipulating camera iso settings. As it will let camera capture more light and you might solve your issue.
Camera camera = Camera.open();
Camera.Parameters params =
camera.getParameters();
params.set("iso", "400");
camera.setParameters(params);
There can be more iso settings as 100,200,1000,auto etc
If you want to isolate this setting only for front cam then just manipulate it if the cam in action is front cam.
Do let me know if this changed anything for you.

Android: Getting Camera preview as tilted

I have made a custom Camera application. And i am getting a Tilted camera view. So i want to know the solution for a correct and a normal preview. I have used setDisplayOrientation() Method. But got no result. Searching for a answer that works.
The Compiling API is 2.3 GingerBread!
Thanks in advance.`
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
String TAG = "MyMsg";
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
Log.d(TAG, "Surface Creation started");
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("MyMsg", "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d("MyMsg", "Error starting camera preview: " + e.getMessage());
}
}
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = 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;
}
camera.setDisplayOrientation(result);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
}
}
`

Nexus 7 Camera (or all front cameras?) are mirrored (upside-down)

To get the camera reference, I do this:
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "Surface created!");
mCamera = Camera.open();
if (mCamera == null) {
// try to open front facing camera
try {
mCamera = Camera.open(0);
} catch (RuntimeException e) {
Toast.makeText(getApplicationContext(),
"No camera available!", Toast.LENGTH_LONG).show();
}
}
try {
mCamera.setPreviewDisplay(mCameraHolder);
setCameraDisplayOrientation(CameraActivity.this, 0, mCamera);
} catch (Exception e) {
e.printStackTrace();
if (mCamera != null)
mCamera.release();
mCamera = null;
}
}
Where setCameraDisplayOrientation is this (which I found on stackoverflow somewhere):
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = 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;
}
camera.setDisplayOrientation(result);
}
When I take a picture with my Nexus 4, it has the right orientation. When I try it with my Nexus 7, which only has a front facing camera, it is mirrored (upside down) (was it even without this piece of code actually, so it kind of does nothing I guess.).
Is there any reliable way to get the camera orientation and to make this work? I've searched on Google and Stackoverflow but did not find anything that works so far.
This is the solution that I found worked with the nexus 7 and majority other devices I tested like HTC One M8, Lenovo Yoga, Lg G4 Nexus 4, Note 4 and the Oneplus One.
camera.setDisplayOrientation(90);
However, this solution doesn't work with the Nexus 6 which flips the preview, so if anyone has a better solution than this please share.

Android Camera recording video but plays upside down

I record a video using the below code and it records perfectly, but when it plays the video, it plays it upside down.
I tried settings mrec.setOrientationHint(180) before mrec.prepare(); but it was useless. Any hints?
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.app.Activity;
import android.hardware.Camera;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
/**
* #author SANA HASSAN
*/
public class CameraSurfaceView extends Activity {
private Preview mPreview;
private MediaRecorder mrec = new MediaRecorder();
private int cameraId = 0;
private Camera mCamera;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
mPreview = new Preview(this);
setContentView(mPreview);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, "Start");
menu.add(0, 1, 0, "Stop");
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 0:
try {
startRecording();
}
catch (Exception e) {
e.printStackTrace();
mrec.release();
}
break;
case 1:
mrec.stop();
mrec.release();
mrec = null;
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
protected void startRecording() throws IOException {
mrec = new MediaRecorder();
mrec.setCamera(mCamera);
mCamera.unlock();
File directory = new File(Environment.getExternalStorageDirectory()+"/NICUVideos");
directory.mkdirs();
mrec.setAudioSource( MediaRecorder.AudioSource.MIC);
mrec.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mrec.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mrec.setOutputFile(Environment.getExternalStorageDirectory()+"/NICUVideos/"+System.currentTimeMillis()+".mp4");
mrec.setPreviewDisplay(mPreview.getHolder().getSurface());
mrec.setVideoSize(640, 480);
Method[] methods = mrec.getClass().getMethods();
for (Method method: methods){
try{
if(method.getName().equals("setAudioEncodingBitRate")){
method.invoke(mrec, 12200);
}
else if(method.getName().equals("setVideoEncodingBitRate")){
method.invoke(mrec, 800000);
}
else if(method.getName().equals("setAudioSamplingRate")){
method.invoke(mrec, 8000);
}
else if(method.getName().equals("setVideoFrameRate")){
method.invoke(mrec, 20);
}
}
catch (IllegalArgumentException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
}
mrec.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mrec.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mrec.setMaxDuration(60000); // 60 seconds
mrec.setMaxFileSize(10000000); // Approximately 10 megabytes
mrec.prepare();
mrec.start();
}
protected void stopRecording() {
mrec.stop();
mrec.release();
mCamera.release();
}
class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Activity activity;
Preview(Activity activity) {
super(activity);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
Camera.CameraInfo info=new Camera.CameraInfo();
for (int i=0; i < Camera.getNumberOfCameras(); i++) {
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
mCamera=Camera.open(i);
cameraId = i;
}
}
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
setCameraDisplayOrientation(mCamera);
mCamera.startPreview();
}
public void setCameraDisplayOrientation(Camera camera) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = CameraSurfaceView.this.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;
}
Log.d(Vars.TAG, "Result = "+result);
camera.setDisplayOrientation(result);
}
}
}
This problem is due to Android handling rotation by just setting some metadata instead of actually rotating the video, and some playback software then ignoring that setting.
As noted in the docs:
Note that some video players may choose to ignore the compostion matrix in a video during playback.
Your options are to either use different playback software that understands the metadata being set, or to re-encode the video after it's been recorded to the correct orientation. It's not clear from your description which of those would be the better solution in your case.
This should be called before the mrec.prepare(); method
setOrientationHint(degrees);
Link
EDIT:
Try mCamera.setDisplayOrientation(degrees);
0 for landscape
90 for portrait
180 & 270 don't work very well and give weird results.
Some older players and encoders do not interpret this flag which is why the video plays upside down.
I know your issue,
Video use Media Recorder from Camera, so you need rotate Media Recorder. use below codes should be fixed your issue.
/**
*
* #param mMediaRecorder
* #return
*/
public static MediaRecorder rotateBackVideo(MediaRecorder mMediaRecorder) {
/**
* Define Orientation of video in here,
* if in portrait mode, use value = 90,
* if in landscape mode, use value = 0
*/
switch (CustomCamera.current_orientation) {
case 0:
mMediaRecorder.setOrientationHint(90);
break;
case 90:
mMediaRecorder.setOrientationHint(180);
break;
case 180:
mMediaRecorder.setOrientationHint(270);
break;
case 270:
mMediaRecorder.setOrientationHint(0);
break;
}
return mMediaRecorder;
}
Should add before prepare() method :
// Step 5: Set the preview output
/**
* Define Orientation of image in here,
* if in portrait mode, use value = 90,
* if in landscape mode, use value = 0
*/
CustomCamera.mMediaRecorder = Utils.rotateBackVideo(CustomCamera.mMediaRecorder);
CustomCamera.mMediaRecorder.setPreviewDisplay(mCameraPreview.getHolder().getSurface());
Thank you
I have the same problem, I note that camera preview orientation angle and recording video angle aren't the same.
So I use this method for change orientation on video recording:
public static int getVideoOrientationAngle(Activity activity, int cameraId) { //The param cameraId is the number of the camera.
int angle;
Display display = activity.getWindowManager().getDefaultDisplay();
int degrees = display.getRotation();
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
switch (degrees) {
case Surface.ROTATION_0:
angle = 90;
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;
}
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
angle = (angle + 180) % 360;
return angle;
}
And that for change orientation on camera preview:
public static int setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = 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;
}
camera.setDisplayOrientation(result);
return result;
}
Note that's important to know if the camera is front or back.
Use OrientationEventListener and track rotation value when device is rotated code here.This code apply rotation to camera but for recording you need apply rotation to MediaRecorder.When you start recording just mMediaRecorder.setOrientationHint(rotation) before mMediaRecorder.prepare(). This solve my problem.
Finally I have found out that Motorola phones have problem in playing the video which is recorded in portrait mode.
In order to overcome the rotation of the video, the best solution I have adopted was to upload the video to the server and run ffmpeg on using the command ffmpeg -i input.mp4 -c:v mpeg4 -c:a copy -c:s copy -vf "transpose=2" output.mp4
If you feel there was another way, please do let me know.
one more solution is to rotate your activity so that its orientation is the same as sensor orientation. That is, landscape for back camera and upside-down portrait for front camera. This btw will not fix mirror effect for the front camera. One more difficulty is that you will have to implement your UI in those rotated activities in a way to follow the activity orientation.
rotate your MediaRecorder like below corresponding the degree you used in Camera display orientation for front facing camera video recording
Display display = ((WindowManager)getContext().getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
parameters.setPreviewSize(height, width);
if(display.getRotation() == Surface.ROTATION_0)
{
mCamera.setDisplayOrientation(90);
mMediaRecorder.setOrientationHint(270);
}
if(display.getRotation() == Surface.ROTATION_90)
{
mMediaRecorder.setOrientationHint(180);
}
if(display.getRotation() == Surface.ROTATION_180)
{
mMediaRecorder.setOrientationHint(270);
}
if(display.getRotation() == Surface.ROTATION_270)
{
mCamera.setDisplayOrientation(180);
mMediaRecorder.setOrientationHint(0);
}
Here is the code for custom portrait camera, will set the correct rotation of picture and video:
private OrientationEventListener orientationEventListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
orientationEventListener = new OrientationEventListener(this) {
#Override
public void onOrientationChanged(int orientation) {
if (orientation == ORIENTATION_UNKNOWN) return;
flashButton.setRotation(-(orientation));
cameraButton.setRotation(-(orientation));
if (camera != null) {
Parameters parameters = camera.getParameters();
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(selectedCamera, info);
orientation = (orientation + 45) / 90 * 90;
int rotation = 0;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotation = (info.orientation - orientation + 360) % 360;
} else { // back-facing camera
rotation = (info.orientation + orientation) % 360;
}
parameters.setRotation(rotation);
if (!isRecording) {
mediaRecorder.setOrientationHint(rotation);
}
camera.setParameters(parameters);
}
}
};
}
#Override
protected void onResume() {
super.onResume();
//...
orientationEventListener.enable();
}
#Override
protected void onPause() {
super.onPause();
orientationEventListener.disable();
//...
}
Teste with portrait orientation. Remeber to put it in your manifest to test code. I dont know if work in landscape.
<activity android:name=".activities.CameraActivity"
android:screenOrientation="portrait">
for portrait mode set your mediaRecorder.setOrientationHint(90); degree is same as your camera orientation myCamera.setDisplayOrientation(90);

Rotating a Camera SurfaceView to portrait

I have looked up a few posts on changing the orientation of the camera with a surface view, but I have taken my code from the examples at:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html
The function that provides the dimensions looks like this...
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
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) {
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;
}
My problem is that when I change the orientation of the device, the preview picture stays landscape. I tried setting the orientation of the camera but this resulted in very strange results. Does anyone know what I need to change to have this rotate properly?
The code to correctly adjust the camera preview orientation is a bit complex, since it has to take into account
The relative orientation of the sensor and the device's 'natural' orientation (which is portrait for phones, landscape for tablets, typically)
The current UI orientation of the device (portrait, landscape or the reverse of each)
Whether the camera in question is the front or the back camera (since the front preview stream is mirrored horizontally)
The documentation for Camera.setDisplayOrientation has sample code on how to deal with this correctly. I'm reproducing it here:
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = 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;
}
camera.setDisplayOrientation(result);
}
Call this after your UI has been drawn (onSurfaceChanged would work as an indicator) or the device UI rotates (onConfigurationChanged would work as an indicator).
I was able to solve the rotation problem by putting the following code in onSurfaceChanged():
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// make any resize, rotate or reformatting changes here
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
mCamera.setDisplayOrientation(90);
} else {
mCamera.setDisplayOrientation(0);
}
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
BUT this created another problem, or better put, didn't solve a problem-while oriented correctly, the preview image still only took up the same amount of space that the landscape view did. I ended up just giving up and forcing landscape orientation with:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
in onCreate() and designed my layout for landscape. Best of luck, and I hope someone has an answer for this secondary problem!
Try this out, but I tried in Samsung Galaxy Tab
public void surfaceCreated(SurfaceHolder holder)
{
// The Surface has been created, acquire the camera and tell it where to draw.
mCamera = Camera.open();
Parameters params = mCamera.getParameters();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
{
params.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
}
try
{
mCamera.setPreviewDisplay(holder);
}
catch (IOException exception)
{
mCamera.release();
mCamera = null;
}
}
I solved this issue by adding:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
To the onCreate event.
Please try this..
#Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height)
{
// TODO Auto-generated method stub
if(previewing)
{
camera.stopPreview();
previewing = false;
}
Camera.Parameters parameters = camera.getParameters();
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
int or=cameraInfo.orientation;
// You need to choose the most appropriate previewSize for your app
// .... select one of previewSizes here
/* parameters.setPreviewSize(previewSize.width, previewSize.height);*/
if(display.getRotation() == Surface.ROTATION_0)
{
camera.setDisplayOrientation(90);
or=90;
}
if(display.getRotation() == Surface.ROTATION_180)
{
camera.setDisplayOrientation(270);
or=270;
}
if(display.getRotation() == Surface.ROTATION_270)
{
camera.setDisplayOrientation(180);
or=180;
}
parameters.setRotation(or);
camera.setParameters(parameters);
try
{
camera.setPreviewDisplay(cameraSurfaceHolder);
camera.startPreview();
previewing = true;
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Well i Do this!
I have solved this issue in in this way in surfaceCreated() method
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();
} catch (RuntimeException e) {
System.err.println(e);
return;
}
Camera.Parameters param;
param = camera.getParameters();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
{
param.set("orientation", "portrait");
setCameraDisplayOrientation(this,1,camera);
}
camera.setParameters(param);
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
System.err.println(e);
return;
}
}
add this method below
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = 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;
}
camera.setDisplayOrientation(result);
}
3: Make sure you have added camera permiison to support for nougat in a activity before this activity calling dont call permission for camera in this activity because surfacecreated call as the activity created, and your permission will be pending to open camera
Only add this
mCamera.setDisplayOrientation(90);

Categories

Resources