编辑
当从倒立竖屏旋转到任一横向方向再返回倒立竖屏时,会出现问题。我在默认相机应用上测试了这些情况,似乎没有这些问题。
结束编辑
我有一个自定义相机,在180度旋转(例如从一种横向到另一种横向)时,预览会倒置。我在代码中使用了OrientationEventListener来处理这个问题。 在setDisplayOrientation中调用mCamera.setDisplayOrientation,使用roundOrientation(orientation, orientationHistory)将方向四舍五入为0、90、180、270,并使用getDisplayRotation获取自然显示旋转。 我在initializeFirstTime中实例化监听器并启用它,在initializeSecondTime中如果从暂停状态恢复则启用它。我在onPause中禁用监听器。在onResume中调用initializeFirstTime或initializeSecondTime。
class MyOrientationEventListener extends OrientationEventListener
{
@Override
public void onOrientationChanged(int orientation)
{
if(orientation==ORIENTATION_UNKNOWN)
return;
mOrientation=roundOrientation(orientation,0);
int orientationCompensation=getDisplayRotation(CameraActivity.this);
if(mOrientationCompensation!=orientationCompensation)
mOrientationCompensation=orientationCompensation;
}
public MyOrientationEventListener(Context context) {
super(context);
}
private int roundOrientation(int orientation, int orientationHistory) {
boolean changeOrientation = false;
final int ORIENTATION_HYSTERESIS=5;//a tolerance value above the limit
if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) {
changeOrientation = true;
} else {
int dist = Math.abs(orientation - orientationHistory);
dist = Math.min(dist, 360 - dist);
changeOrientation = (dist >= 45 +ORIENTATION_HYSTERESIS );
}
if (changeOrientation) {
return ((orientation + 45) / 90 * 90) % 360;
}
return orientationHistory;
}
}
private void setDisplayOrientation()
{
mDisplayRotation=getDisplayRotation(this);
mDisplayOrientation=getDisplayOrientation(mDisplayRotation, CameraInfo.CAMERA_FACING_BACK);
mCamera.setDisplayOrientation(mDisplayOrientation);
}
private int getDisplayOrientation(int degrees, int cameraId) {
// See android.hardware.Camera.setDisplayOrientation for
// documentation.
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
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;
}
private int getDisplayRotation(Activity activity) {
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
switch (rotation) {
case Surface.ROTATION_0: return 0;
case Surface.ROTATION_90: return 90;
case Surface.ROTATION_180: return 180;
case Surface.ROTATION_270: return 270;
}
return 0;
}
private MyOrientationEventListener mOrientationListener;
private int mOrientation=OrientationEventListener.ORIENTATION_UNKNOWN;
private int mOrientationCompensation=0;
private int mDisplayRotation;
private int mDisplayOrientation;
这两种方法用于激活OrientationEventListener:
private void initializeFirstTime()
{
//checking if previously initialized and setting camera parameters
mOrientationListener=new MyOrientationEventListener(CameraActivity.this);
mOrientationListener.enable();
mFirstTimeInitialized=true;
}
private void initializeSecondTime()
{
mOrientationListener.enable();
}
相机预览的启动、停止和重新启动的方式如下:
private void startPreview() throws CameraHardwareException
{
//check if called before onPause or after onResume,
//open the Camera if null,stop the preview,set the parameters
setDisplayOrientation();
try
{
Log.d(TAG, "Trying to start the preview");
mCamera.startPreview();
}
catch(Throwable ex)
{
closeCamera();
throw new RuntimeException("Could not start camera preview");
}
mPreviewing=true;
}
Activity生命周期方法的实现方式如下:
@Override
public void onResume()
{
super.onResume();
mPausing=false;
//check condition for SurfaceHolder
//probsbly happens if camera has paused and is resuming
if(mStatus==PREVIEW_STOPPED)
{
try {
startPreview();
} catch (CameraHardwareException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(surfaceHolder!=null)
{
if(!mFirstTimeInitialized)
initializeFirstTime();
else
initializeSecondTime();
}
keepScreenOnAwhile();
if(mStatus==CAMERA_IDLE)
{
mResumeTime=SystemClock.uptimeMillis();
handler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100);
}
}
@Override
public void onPause()
{
mPausing=true;
stopPreview();
closeCamera();
resetScreenOn();
if(mFirstTimeInitialized)
mOrientationListener.disable();
handler.removeMessages(FIRST_TIME_INIT);
handler.removeMessages(CLEAR_SCREEN_DELAY);
super.onPause();
}
这里已经实现了SurfaceHolder.Callbacks方法:
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if(holder.getSurface()==null)
{
Log.d(TAG, "holder.getSurface()=null");
return;
}
//stash the holder here for later use,useful if onResume needs to be invoked after this.
surfaceHolder=holder;
if(mCamera==null)
return;
//sometimes surfaceChanged is called after onPause or before onResume,ignore it
if(mPausing || isFinishing())
return;
if(mStatus==PREVIEW_STOPPED)
try {
startPreview();
} catch (CameraHardwareException e1) {
Log.e(TAG, "Error starting the preview");
}
if(!mPreviewing)
try {
startPreview();
} catch (CameraHardwareException e) {
Log.e(TAG,"Could not get the camera");
}
if(!mFirstTimeInitialized)
if(getDisplayRotation(this)!=mDisplayOrientation)
setDisplayOrientation();
if(mPreviewing && holder.isCreating())
{
setPreviewDisplay(holder);
}
if(!mFirstTimeInitialized)
handler.sendEmptyMessage(FIRST_TIME_INIT);
else
initializeSecondTime();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//nothing here
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
stopPreview();
surfaceHolder=null;
}
在 onResume 和 surfaceChanged 中启用方向事件监听器,哪一个先调用就先执行,并在 onPause 中禁用。OrientationEventListener 只在 initializeFirstTime 中实例化。
编辑:
这是因为我没有正确启用 OrientationEventListener 吗?同时,我是否正确设置了影响图像旋转的参数旋转:
mParameters.setRotation(rotation);
android:screenOrientation=fullSensor
。 - Alex Cohnandroid:screenOrientation=fullSensor
。已尝试通过 SurfaceHolder.Callbacks 进行更改。 - vamsiampolulayout-land
ن¸و²،وœ‰و·»هٹ ن»»ن½•ه¸ƒه±€و–‡ن»¶ç»™CameraActivity
,è؟™ن¼ڑوœ‰ن»€ن¹ˆه½±ه“چهگ—ï¼ں - vamsiampolu