相机:setDisplayOrientationfunction不适用于Android 2.3.6的三星Galaxy ACE

我试图创build一个简单的相机应用程序的研究。 我阅读Android相机正式文件 ,然后开始编码。 所以我做了一些步骤来实现它的工作

1.在应用程序中添加了相机function所需的权限。

2.我的活动只locking在肖像模式。

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

3.添加了几个相机callback让我的相机工作。

  • SurfaceHolder.Callback,
  • Camera.PreviewCallback
  • AutoFocusCallback
  • ShutterCallback
  • RAW图像数据的PictureCallback
  • PictureCallback用于JPG图像数据

4.在surfaceChanged方法中,我正在自定义相机设置。 到目前为止,我已经为几乎所有的Android设备工作

  • LG
  • 香料
  • 三星
  • HTC
  • 福邦
  • 索尼
  • 摩托罗拉
  • 谷歌Nexus系列。

后来我在Android 2.3.6版本的三星Galaxy ACE上testing,发现相机显示预览旋转到横向模式。

所以在把log-cat / break点后,我才知道下面的方法不适用于这个特定的模型

//This method is not working for Samsung Galaxy ACE camera.setDisplayOrientation(90); //or parameters.set("orientation", "portrait"); //or parameters.setRotation(90); 

注意: 我在Google和SO上都搜集了很多的解决scheme,但是到目前为止,还没有得到任何好运

  • Issus 在这里报道
  • 安卓相机的Surfaceview方向
  • Android人像locking相机预览
  • Android – 相机预览横向
  • Android相机旋转
  • Android:相机预览旋转
  • 如何正确设置Android相机方向?

供您参考我的示例代码如下

 @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(); } } } 

我的相机活动(MainActivity.java)完整的代码是:

 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; } } 

编辑 :我发表了评论开发者论坛,但没有回应。

请!! 有人对这个问题有任何想法。

我真的很感激任何forms的build议。

Solutions Collecting From Web of "相机:setDisplayOrientationfunction不适用于Android 2.3.6的三星Galaxy ACE"

当我在运行2.2.1的原始Galaxy Tab中遇到类似的问题时,我可以通过以下操作来解决这个问题:

 Camera.Parameters parameters = camera.getParameters(); parameters.set("orientation", "portrait"); parameters.setRotation(90); camera.setParameters(parameters); 

然而,看起来你可能已经尝试了这个确切的组合,因为你有相同的(但注释掉)上面的代码。 然而,现在你有代码的方式,因为它的API级别(10),Ace将绕过你已经注释过的代码。 在这个块里专门尝试一下:

 if (currentSDKVersion != 7) { } 

请让我知道它是否有效。 谢谢!

我也在寻找一个解决scheme。 它真的很疯狂。 我的解决scheme是在横向模式(在我的肖像应用程序)中使用相机预览,并掩盖预览中不需要的部分。 我通过覆盖我的全屏预览的上下部分与一些视图做到了这一点。 因为你必须裁剪你从照相机得到的照片,那么结果就会降低。 对于我的应用程序,这是没有问题。

我现在对我的解决scheme非常满意 – 用户没有看到任何区别。

我通过编写一些主要适用于ZXing项目的代码来处理相机: http : //code.google.com/p/zxing/

你可以尝试使用这些。 如果你正在尝试使用这个,我会build议通过这个问题的解决scheme

这可能不是你的问题的完美解决scheme,但我已经跑过这个问题,并决定使用Zxing。