Cámara: la función setDisplayOrientation no funciona para Samsung Galaxy ACE con Android 2.3.6
camera android-camera (3)
Estaba tratando de crear una aplicación de cámara simple para la investigación. Leí el documento oficial de la cámara Android y luego comencé a codificar. Así que hice algunos pasos para que funcione.
1. Se agregaron los permisos necesarios para la función de cámara en la aplicación.
2.bloquea mi actividad al modo RETRATO solo.
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
3. Agregado varias devoluciones de llamada de la cámara para que mi cámara funcione.
- SurfaceHolder.Callback,
- Camera.PreviewCallback
- AutoFocusCallback
- ShutterCallback
- PictureCallback para datos de imagen RAW
- PictureCallback para datos de imagen JPG
4.En un método de cambio de superficie , estoy personalizando la configuración de la cámara. y hasta ahora me puse a trabajar esto para casi todos los dispositivos Android
- LG
- especia
- Samsung
- HTC
- Micromax
- Sony
- Motorola
- Serie Google Nexus.
Pero luego lo probé en Samsung Galaxy ACE con la versión de Android 2.3.6 y encontré que la vista previa de la pantalla de la cámara está girada a modo horizontal.
Entonces, después de poner log-cat / break points, me doy cuenta de que los métodos a continuación no funcionan para este modelo en particular.
//This method is not working for Samsung Galaxy ACE
camera.setDisplayOrientation(90);
//or
parameters.set("orientation", "portrait");
//or
parameters.setRotation(90);
Nota: también he encontrado muchas soluciones sobre Google y SO, pero hasta ahora no he tenido suerte en esto.
- Issus informó here
- orientación de la cámara de Android orientación
- Vista previa de la cámara bloqueada con Android
- Android: la vista previa de la cámara es lateral
- Cámara de Android girar
- Android: Vista previa de la cámara girada
- ¿Cómo configurar correctamente la orientación de la cámara Android?
Para su referencia, mi código de muestra está abajo.
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
Log.v(TAG, "surfaceChanged get called");
if (previewing) {
camera.stopPreview();
previewing = false;
}
if (camera != null) {
try {
Camera.Parameters parameters = camera.getParameters();
List<Size> sizes = parameters.getSupportedPictureSizes();
Camera.Size result = null;
for (int i = 0; i < sizes.size(); i++) {
result = (Size) sizes.get(i);
Log.i("PictureSize", "Supported Size. Width: "
+ result.width + "height : " + result.height);
if (result.width == 640) {
parameters.setPreviewSize(result.width, result.height);// 640*480
parameters.setPictureSize(result.width, result.height);
} else {
}
}
//**************************************************************//
/*
* Here is the logic I have added to Manage Camera Display Orientation
* It checks Current Orientation and SDK and then rotate display to make it Portrait view.
*/
int currentSDKVersion = android.os.Build.VERSION.SDK_INT;
Log.d(TAG, "currentVersion " + currentSDKVersion);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
if (currentSDKVersion != 7) {
camera.setDisplayOrientation(90);
parameters.setRotation(90);
} else {
parameters.setRotation(90);
/*
* params.set("orientation", "portrait");
* params.set("rotation",90);
*/
}
} else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (currentSDKVersion != 7) {
camera.setDisplayOrientation(0);
} else {
parameters.set("orientation", "landscape");
parameters.set("rotation", 90);
}
}
//**************************************************************//
camera.setParameters(parameters);
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
camera.autoFocus(myAutoFocusCallback);
camera.setOneShotPreviewCallback(cameraPreviewCallback);
previewing = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
Mi actividad de cámara (MainActivity.java) El código completo es:
public class MainActivity extends Activity implements SurfaceHolder.Callback,
OnClickListener {
public static final String TAG = "CameraActivity";
private Context context = null;
Camera camera = null;
private SurfaceView surfaceView = null;
private SurfaceHolder surfaceHolder = null;
boolean previewing = false;
private LayoutInflater controlInflater = null;
private Button buttonTakePicture = null;
//private TextView textViewResultInfo = null;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.v(TAG, "onCreate get called");
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//textViewResultInfo = (TextView) findViewById(R.id.textViewResultInfo);
context = this;
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.control, null);
LayoutParams layoutParamsControl = new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
this.addContentView(viewControl, layoutParamsControl);
buttonTakePicture = (Button) findViewById(R.id.takepicture);
buttonTakePicture.setOnClickListener(this);
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
Log.v(TAG, "surfaceCreated get called");
camera = Camera.open();
if (camera != null) {
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
Log.v(TAG, "surfaceChanged get called");
if (previewing) {
camera.stopPreview();
previewing = false;
}
if (camera != null) {
try {
//new MainActivity().setCameraDisplayOrientation();
Camera.Parameters parameters = camera.getParameters();
// List<String> focusModes =
// parameters.getSupportedFocusModes();
// if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO))
// {
// parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// }
List<Size> sizes = parameters.getSupportedPictureSizes();
Camera.Size result = null;
for (int i = 0; i < sizes.size(); i++) {
result = (Size) sizes.get(i);
Log.i("PictureSize", "Supported Size. Width: "
+ result.width + "height : " + result.height);
if (result.width == 640) {
parameters.setPreviewSize(result.width, result.height);// 640*480
parameters.setPictureSize(result.width, result.height);
} else {
}
}
//**************************************************************//
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int rotation = display.getRotation();
Log.v(TAG, "Current Device Orientation is ="+rotation);
/*
* Here is the logic I have added to Manage Camera Display Orientation
* It checks Current Orientation and SDK and then rotate display to make it Portrait view.
*/
int currentSDKVersion = android.os.Build.VERSION.SDK_INT;
Log.d(TAG, "currentVersion " + currentSDKVersion);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
if (currentSDKVersion != 7) {
Log.i(TAG, "ORIENTATION_PORTRAIT +SDK is: " + currentSDKVersion
+ "rotate 90");
camera.setDisplayOrientation(90);
parameters.setRotation(90);
} else {
Log.i(TAG, "ORIENTATION_PORTRAIT +SDK is: " + currentSDKVersion
+ "rotate 90");
parameters.setRotation(90);
/*
* params.set("orientation", "portrait");
* params.set("rotation",90);
*/
}
} else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (currentSDKVersion != 7) {
Log.i(TAG, "ORIENTATION_LANDSCAPE +SDK is: " + currentSDKVersion
+ "rotate 90");
camera.setDisplayOrientation(0);
} else {
Log.i(TAG, "ORIENTATION_LANDSCAPE +SDK is: " + currentSDKVersion
+ "rotate 90");
parameters.set("orientation", "landscape");
parameters.set("rotation", 90);
}
}
//**************************************************************//
camera.setParameters(parameters);
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
camera.autoFocus(myAutoFocusCallback);
camera.setOneShotPreviewCallback(cameraPreviewCallback);
previewing = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
Log.v(TAG, "surfaceDestroyed get called");
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
public void setCameraDisplayOrientation()
{
Log.v(TAG, "setCameraDisplayOrientation get called");
if (camera == null)
{
Log.d(TAG,"setCameraDisplayOrientation - camera null");
return;
}
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(1, info);
WindowManager winManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
int rotation = winManager.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
public void onClick(View v) {
Log.v(TAG, "onClick get called");
if (v == buttonTakePicture) {
camera.takePicture(myShutterCallback, myPictureCallback_RAW,
myPictureCallback_JPG);
}
}
private Camera.PreviewCallback cameraPreviewCallback = new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
Log.i(TAG, "onPreviewFrame size=" + data.length);
}
};
AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback() {
@Override
public void onAutoFocus(boolean arg0, Camera arg1) {
Log.v(TAG, "onAutoFocus get called");
buttonTakePicture.setEnabled(true);
}
};
ShutterCallback myShutterCallback = new ShutterCallback() {
@Override
public void onShutter() {
Log.v(TAG, "onShutter get called");
}
};
PictureCallback myPictureCallback_RAW = new PictureCallback() {
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
Log.v(TAG, "onPictureTaken-RAW get called");
}
};
public static Bitmap RotateBitmap(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(),
source.getHeight(), matrix, true);
}
PictureCallback myPictureCallback_JPG = new PictureCallback() {
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
Bitmap rawImage = BitmapFactory.decodeByteArray(arg0, 0,
arg0.length);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
Log.v(TAG, "##### ORIENTATION_PORTRAIT ####");
rawImage = MainActivity.RotateBitmap(rawImage, 90);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
rawImage.compress(Bitmap.CompressFormat.JPEG, 100, stream);
arg0 = stream.toByteArray();
} else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
Log.v(TAG, "##### ORIENTATION_LANDSCAPE #####");
}
Intent intent = new Intent(MainActivity.this, ResultActivity.class);
intent.putExtra("picture", arg0);
startActivity(intent);
Log.v(TAG, "onPictureTaken-JPG get called");
}
};
/**
* Get the size in bitmap.
*
* @param bitmap
* @return size in bytes
*/
@TargetApi(12)
public static int getBitmapSize(Bitmap bitmap) {
if (MainActivity.hasHoneycombMR1()) {
return bitmap.getByteCount();
}
// Pre HC-MR1
return bitmap.getRowBytes() * bitmap.getHeight();
}
public static boolean hasHoneycombMR1() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1;
}
}
Edit : He publicado un comentario en el foro de desarrolladores, pero no hay respuesta.
¡¡Por favor!! Alguien tiene alguna idea con respecto a este problema.
Realmente agradecería cualquier tipo de sugerencia.
Cuando tuve un problema similar con la versión original de Galaxy Tab 2.2.1, pude resolverlo haciendo lo siguiente:
Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
parameters.setRotation(90);
camera.setParameters(parameters);
Sin embargo, parece que es posible que ya hayas probado esa combinación exacta, dado que tienes el código idéntico (pero comentado) de arriba. Sin embargo, de la forma en que tiene el código en este momento, el Ace pasará por alto donde tiene ese código comentado debido a su nivel de API (10). Pruébalo específicamente dentro de este bloque:
if (currentSDKVersion != 7) { }
Y déjame saber si funciona, por favor. ¡Gracias!
Estaba buscando una solución por horas también. Es realmente una locura. Mi solución fue utilizar la vista previa de la cámara en modo horizontal (en mi aplicación vertical) y enmascarar las partes de la vista previa que no necesito. Hice esto superponiendo pars superior e inferior de mi vista previa de pantalla completa con algunas vistas. Por la razón, tiene que recortar la foto que está obteniendo de la cámara y, QUÉ RESULTA EN MENOS RESOLUCIÓN. Para mi aplicación esto no fue un problema.
Estoy totalmente feliz con mi solución ahora; los usuarios no ven ninguna diferencia;
Manejé la cámara escribiendo un código que se adaptó principalmente del proyecto ZXing: http://code.google.com/p/zxing/
Podrías intentar usarlos. Si está intentando usar esto, le recomendaría que vaya a la solución de esta pregunta de .
Es posible que esta no sea la solución perfecta para su pregunta, pero me encontré con este problema y decidí usar Zxing.