I have created a camera app and I want my app to be turned in all 4 possible orientations and the to update the camera preview accordingly. for that I have used the following method I have copied from:
Android - Camera preview is sideways
public void updateCameraDisplay(int w, int h) {
// set preview size and make any resize, rotate or
// reformatting changes here
Log.i("CameraPreviews", "Updating camera orientation with w=" + w
+ " and h=" + h);
Parameters parameters = camera.getParameters();
Display display = getActivity().getWindowManager()
.getDefaultDisplay();
int rotation = getActivity().getResources().getConfiguration().orientation;
Log.i("CameraPreviews", "rotation is " + display.getRotation());
if (display.getRotation() == Surface.ROTATION_0) {
parameters.setPreviewSize(h, w);
camera.setDisplayOrientation(0);
}
if (display.getRotation() == Surface.ROTATION_90) {
parameters.setPreviewSize(w, h);
camera.setDisplayOrientation(270);
}
if (display.getRotation() == Surface.ROTATION_180) {
parameters.setPreviewSize(h, w);
camera.setDisplayOrientation(180);
}
if (display.getRotation() == Surface.ROTATION_270) {
parameters.setPreviewSize(w, h);
camera.setDisplayOrientation(90);
}
try {
camera.setParameters(parameters);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I have tweeked the values, testing them on the samsung galaxy tab2 to finally get the right orientations and it all works. When I tried it on htc one s phone it doesn't work at all!!!!! All e orientations are totally wrong! So I have arrived to the conclusion that thre must be 2 type of devices (or more... please no!) because the rotation represents how many degrees the screen has been rotated from its "default" position then some devices have one default position and others another. How could I find out about this default rotation and act accordingly in my code?
ej:
defaultOrientation=some code
if(defaultOrientation==0) ...
else ....
locking screen orientation is out of question.
target api>=11
thanks a lot
EDIT:
I have modified my code to:
public void updateCameraDisplay(int w, int h) {
// set preview size and make any resize, rotate or
// reformatting changes here
Log.i("CameraPreviews", "Updating camera orientation with w=" + w
+ " and h=" + h);
Parameters parameters = camera.getParameters();
Display display = getActivity().getWindowManager()
.getDefaultDisplay();
int rotation = getActivity().getResources().getConfiguration().orientation;
Log.i("CameraPreviews", "screen rotation is " + rotation);
Log.i("CameraPreviews", "display rotation is " + display.getRotation());
if (display.getRotation() == Surface.ROTATION_0) {
if (rotation == Configuration.ORIENTATION_LANDSCAPE) {
parameters.setPreviewSize(h, w);
camera.setDisplayOrientation(0);
} else {
parameters.setPreviewSize(h, w);
camera.setDisplayOrientation(90);
}
}
else if (display.getRotation() == Surface.ROTATION_90) {
if (rotation == Configuration.ORIENTATION_PORTRAIT) {
parameters.setPreviewSize(w, h);
camera.setDisplayOrientation(270);
} else {
parameters.setPreviewSize(w, h);
//camera.setDisplayOrientation(0);
}
}
else if (display.getRotation() == Surface.ROTATION_180) {
if (rotation == Configuration.ORIENTATION_LANDSCAPE) {
parameters.setPreviewSize(h, w);
camera.setDisplayOrientation(180);
}else {
parameters.setPreviewSize(h, w);
camera.setDisplayOrientation(270);
}
}
else if (display.getRotation() == Surface.ROTATION_270) {
if (rotation == Configuration.ORIENTATION_PORTRAIT) {
parameters.setPreviewSize(w, h);
camera.setDisplayOrientation(90);
} else {
parameters.setPreviewSize(w, h);
camera.setDisplayOrientation(180);
}
}
try {
camera.setParameters(parameters);
} catch (Exception e) {
e.printStackTrace();
}
}
works better on htc one s and samsung galaxy tab as long as we don't rotate the phone in the portrait mode upside down
the factors you need to think about are: the orientation of the device, the degree between the screen and the camera, assuming you are using the back camera, and whether you enable the activity to sense the orientation change.
And one important thing is whether the Camera HAL code implemented by the manufacturer is compliant with Google's protocol.
Related
I'm developing a small camera capture program in android.
I didn't use the Intent to open the camera and show it's images. I'm using the camera directly:
if (myPreviewRunning) {
myCamera.stopPreview();
myPreviewRunning = false;
}
Camera.Parameters parameters = myCamera.getParameters();
display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
display = getWindowManager().getDefaultDisplay();
Camera.Size optimalSize = getOptimalSize(parameters.getSupportedPreviewSizes(), width, height);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
if (display.getRotation() == Surface.ROTATION_0 ||display.getRotation() == Surface.ROTATION_270)
{
parameters.setPreviewSize(optimalSize.height, optimalSize.width);
ViewGroup.LayoutParams layoutParams = mySurfaceView.getLayoutParams();
layoutParams.width = optimalSize.height;
layoutParams.height = optimalSize.width;
mySurfaceView.setLayoutParams(layoutParams);
myCamera.setDisplayOrientation(90);
}
else
{
myCamera.setDisplayOrientation(180);
mySurfaceView.getLayoutParams().width = optimalSize.width;
mySurfaceView.getLayoutParams().height = optimalSize.height;
}
myCamera.setParameters(parameters);
myCamera.setPreviewDisplay(holder);
myCamera.startPreview();
Until now, with this code I'm able to rotate the camera to a 'natural' behaviour, so when I rotate the cell phone to landscape, it rotates the image and you see it in landscape. But due to some reasons, I need the preview image to remain in portrait mode, even if I put landscape.
How can I force the camera preview to remain in portrait mode?
EDIT: AndroidManifest.xml
<activity
android:name="CameraViewer"
android:label="#string/app_name"
android:screenOrientation="portrait" >
</activity>
I want to be able to do this:
I am using this code:
https://github.com/commonsguy/cw-advandroid/blob/master/Camera/Picture/src/com/commonsware/android/picture/PictureDemo.java
where in Manifest, Activity Orientation is set to Landscape.
So, its like allowing user to take picture only in Landscape mode, and if the picture is taking by holding the device in portrait mode, the image saved is like this:
a 90 degree rotated image.
After searching for a solution, I found this:
Android - Camera preview is sideways
where the solution is:
in surfaceChanged() check for
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
display.getRotation();
and change the Camera's displayOrientation accordingly.
camera.setDisplayOrientation(90);
But no matter how many times I rotate the device, surfaceChanged() never gets called.
I even tried removing orientation="Landscape" in the Manifest.xml, but then the preview itself is shown sideways(may be because default android.view.SurfaceView is supposed to be in Landscape mode?).
Try this.
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();
camParam = camera.getParameters();
Camera.Parameters params = camera.getParameters();
String currentversion = android.os.Build.VERSION.SDK;
Log.d("System out", "currentVersion " + currentversion);
int currentInt = android.os.Build.VERSION.SDK_INT;
Log.d("System out", "currentVersion " + currentInt);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
if (currentInt != 7) {
camera.setDisplayOrientation(90);
} else {
Log.d("System out", "Portrait " + currentInt);
params.setRotation(90);
/*
* params.set("orientation", "portrait");
* params.set("rotation",90);
*/
camera.setParameters(params);
}
}
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
// camera.setDisplayOrientation(0);
if (currentInt != 7) {
camera.setDisplayOrientation(0);
} else {
Log.d("System out", "Landscape " + currentInt);
params.set("orientation", "landscape");
params.set("rotation", 90);
camera.setParameters(params);
}
}
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (IOException e) {
Log.d("CAMERA", e.getMessage());
}
}
Since you've forced your application to be landscape, your application's configuration won't change when you rotate the device, and as a result, your UI won't get redrawn. So you'll never see a surfaceCreated/Changed callback because of it.
In any case, your issue isn't with preview, it's with the captured pictures.
The camera API doesn't automatically know which way is down; it needs you to tell it how you want your images rotated by using the Camera.Parameters setRotation method. There are several coordinate systems in play here (the orientation of the camera sensor relative to your device; the orientation of your UI relative to the device; and the orientation of the device relative to the world) which have to be done correctly.
So I highly recommend you use the code provided in the setRotation documentation, and inherit from the OrientationEventListener, implementing the listener as follows:
public void onOrientationChanged(int orientation) {
if (orientation == ORIENTATION_UNKNOWN) return;
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, 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;
}
mParameters.setRotation(rotation);
}
This will update your camera's still picture orientation correctly so that 'up' is always up, whether your app is landscape or portrait, or your device is a tablet or a phone.
For my application I am using android native camera and previewing the image using surface view. in my case everything is working except the camera orientation. When I open the camera by setting screenOrientation="landscape on manifest file I am getting the preview without any problem in landscape mode. But I need to take image in portrait mode, for this I changed my manifest like android:screenOrientation="portrait" and change my code like mCamera.setDisplayOrientation(90), params.set("orientation", "landscape"),params.set("rotation", 90), but still I am getting 90 degree rotated image.
And my code is
public void setupCamera(int width, int height) {
Log.i(TAG, "setupCamera");
synchronized (this) {
if (mCamera != null) {
Camera.Parameters params = mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
List<Camera.Size> imgsize=params.getSupportedPictureSizes();
mFrameWidth = width;
mFrameHeight = height;
// mCamera.setDisplayOrientation(90);
params.set("orientation", "landscape");
params.set("rotation", 90);
// selecting optimal camera preview size
{
int minDiff = Integer.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - height) < minDiff) {
mFrameWidth = size.width;
mFrameHeight = size.height;
minDiff = Math.abs(size.height - height);
}
}
}
params.setPreviewSize(getFrameWidth(), getFrameHeight());
List<String> FocusModes = params.getSupportedFocusModes();
if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
{
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(params);
mCamera.startPreview();
}
}
}
I am using Micromax A 52 model...
Any one please help.....
If your application runs on v2.2 or above you can rotate camera orientation to portrait using camera.setDisplayOrientation(90).
For others:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//After opening camera - call via reflection
Method rotateMethod = android.hardware.Camera.class.getMethod("setDisplayOrientation", int.class);
rotateMethod.invoke(mCamera, 90);
for more details please refer this link and this Hope this will be helpful
I have an application that taking a photo in android.
It crashed some devices. I set the photo size as follows.
What could be the reason for the crash?
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
Camera.Parameters parameters = camera.getParameters();
List<Size> sizes = parameters.getSupportedPictureSizes();
if (sizes == null || sizes.size() == 0)
{
parameters.setPreviewSize(w, h);
} else
{
parameters.setPictureSize(sizes.get(0).width, sizes.get(0).height);
for(Size s : sizes)
{
if( s.width < 700)
{
parameters.setPictureSize(s.width, s.height);
break;
}
}
}
camera.setParameters(parameters);
camera.startPreview();
}
Guys I know that it's a old post though I came across the same issue though this time everything worked on Samsung and Nexus line though not on HTC (due Sense for sure). What I've done to fix this issue was loop through all supported sizes and get the one that is supported.
In fact it's crash when I did try to setParamters, because the maximun Picture size supported value. So I did a small method that loop through it and set the one that is accepted by the device.
private void setCameraParameters() {
if (camera != null) {
mParameters = camera.getParameters();
List<Camera.Size> sizes = mParameters.getSupportedPreviewSizes();
Camera.Size selected = sizes.get(0);
if (android.os.Build.MANUFACTURER.contains("HTC")) {
getHTCBestSupportedResolution(sizes);
}
mParameters.setColorEffect(Camera.Parameters.EFFECT_MONO);
mParameters.setJpegQuality(100);
mParameters.setPreviewSize(selected.width, selected.height);
mParameters.setRotation(90);
mParameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
mParameters.setPictureFormat(ImageFormat.JPEG);
camera.setParameters(mParameters);
camera.setDisplayOrientation(90);
camera.startPreview();
}
}
private void getHTCBestSupportedResolution(List<Camera.Size> sizes) {
for (Size size : sizes) {
try {
mParameters.setPictureSize(size.width, size.height);
camera.setParameters(mParameters);
// Log.e("Size worked", size.width + " x " + size.height);
break;
} catch (Exception e) {
continue;
}
}
}
Now it's works fine on all devices, as rule of thumb you can remove the condition that compare for HTC and just let it generic for all devices.
I hope that this help those ones facing the same issue.
Thanks
Check Logcat, I guess it crashes on
camera.setParameters(parameters);
On some devices some of the reported supported resolutions don't seem to be actually supported. You can try to find a legacy resolution, that is supported on all devices. Or catch the exception and try to set another resolution.
I face a problem a problem trying to have a camera preview in portrait mode. I have read various articles about it and I had solved it having the following code:
Display display = ((CaptureActivity)context).getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
if (Integer.parseInt(Build.VERSION.SDK) >= 8) {
setDisplayOrientation(camera, 90);
}else{
Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
camera.setParameters(parameters);
}
where setDisplayOrientation() is defined as:
protected void setDisplayOrientation(Camera camera, int angle) {
Method downPolymorphic;
try {
downPolymorphic = camera.getClass().getMethod(
"setDisplayOrientation", new Class[] { int.class });
if (downPolymorphic != null)
downPolymorphic.invoke(camera, new Object[] { angle });
} catch (Exception e1) {
}
}
Now I tried this code to a Galaxy Tab and it failed. I solved it (trying and error approach) using the following code:
if (height == 1024 && width == 600) {
Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
parameters.setRotation(90);
camera.setParameters(parameters);
}
Now my two questions are:
1) Why there is such problem while Galaxy tab has the 2.2 version, and
2) Is there any better solution to this problem?
Thanks a lot for your time!
for setting the display orientation check out the official docs, dont just hardcode 90 degrees there.