gpt4 book ai didi

android - 旋转后未调用 surfaceCreated()

转载 作者:行者123 更新时间:2023-11-30 03:28:14 33 4
gpt4 key购买 nike

我的主要 Activity 是展示相机预览。当我旋转手机时,应用程序关闭。在日志中,我看到旋转后从未调用 surfaceCreated() 和 surfaceChanged(),然后调用了 main 的 onStop()。

摩托罗拉和三星手机表现出相同的行为。我的应用程序中的其他 Activity 按预期在轮换中幸存下来。

我认为问题可能出在过时的预览引用上,但日志显示了新的持有者和预览实例。

  1. 为什么在轮换后不调用 holder 回调?
  2. 我可以强制叫他们吗?

日志 fragment

07-27 08:32:12.093: I/MainActivity(21285):   
07-27 08:32:12.093: I/MainActivity(21285): ***********STARTING APP*****************
07-27 08:32:12.093: I/MainActivity(21285): onCreate
07-27 08:32:12.093: I/MainActivity(21285):
07-27 08:32:12.289: I/StackOPreview(21285): in constructor
07-27 08:32:12.289: V/StackOPreview(21285): holder: android.view.SurfaceView$3@4053af90
07-27 08:32:12.289: V/StackOPreview(21285): this: com.chex.camera.StackOPreview@4053aba0
07-27 08:32:12.296: I/MainActivity(21285): onCreate finished
07-27 08:32:12.296: I/MainActivity(21285):
07-27 08:32:12.296: I/MainActivity(21285): ||||||||||||||||||| ON RESUME |||||||||||||||||||
07-27 08:32:12.296: I/MainActivity(21285):
07-27 08:32:12.367: I/StackOPreview(21285): surfaceCreated
07-27 08:32:12.375: I/StackOPreview(21285): view width: 540 height: 960
07-27 08:32:12.375: I/StackOPreview(21285): portrait mode so rotate camera preview
07-27 08:32:12.382: I/CameraSettings(21285): retreiving portrait orientation
07-27 08:32:12.382: I/SettingsCP(21285): starting Settings ContentProvider query
07-27 08:32:12.421: I/SettingsCP(21285): got 1 settings
07-27 08:32:12.421: I/CameraSettings(21285): retrieved portrait orientation= 90
07-27 08:32:12.429: I/CameraSettings(21285):
07-27 08:32:12.429: I/CameraSettings(21285): retreiving portrait rotation
07-27 08:32:12.429: I/SettingsCP(21285): starting Settings ContentProvider query
07-27 08:32:12.429: I/SettingsCP(21285): got 1 settings
07-27 08:32:12.429: I/CameraSettings(21285): retrieved portrait rotation= 90
07-27 08:32:12.429: I/CameraSettings(21285):
07-27 08:32:12.468: I/StackOPreview(21285): setting View measured dimensions to width: 540 height: 960
07-27 08:32:12.468: I/StackOPreview(21285): optimal preview width: 1920 height: 1080
07-27 08:32:13.929: I/StackOPreview(21285): surfaceChanged
07-27 08:32:14.085: I/StackOPreview(21285): view width: 540 height: 960
07-27 08:32:14.085: I/StackOPreview(21285): portrait mode so rotate camera preview
07-27 08:32:14.085: I/CameraSettings(21285): retreiving portrait orientation
07-27 08:32:14.085: I/SettingsCP(21285): starting Settings ContentProvider query
07-27 08:32:14.085: I/SettingsCP(21285): got 1 settings
07-27 08:32:14.085: I/CameraSettings(21285): retrieved portrait orientation= 90
07-27 08:32:14.085: I/CameraSettings(21285):
07-27 08:32:14.085: I/CameraSettings(21285): retreiving portrait rotation
07-27 08:32:14.085: I/SettingsCP(21285): starting Settings ContentProvider query
07-27 08:32:14.085: I/SettingsCP(21285): got 1 settings
07-27 08:32:14.093: I/CameraSettings(21285): retrieved portrait rotation= 90
07-27 08:32:14.093: I/CameraSettings(21285):
07-27 08:32:14.101: I/StackOPreview(21285): setting View measured dimensions to width: 540 height: 960
07-27 08:32:14.101: I/StackOPreview(21285): optimal preview width: 1920 height: 1080
07-27 08:32:27.109: I/MainActivity(21285):
07-27 08:32:27.109: I/MainActivity(21285): ||||||||||||||||||| ON PAUSE |||||||||||||||||||
07-27 08:32:27.109: I/MainActivity(21285):
07-27 08:32:27.757: I/StackOPreview(21285): onPause
07-27 08:32:27.757: I/MainActivity(21285): releasing camera in onPause
07-27 08:32:27.757: E/MainActivity(21285): onStop
07-27 08:32:27.757: I/MainActivity(21285):
07-27 08:32:27.757: I/MainActivity(21285): ||||||||||||||||||| ON STOP |||||||||||||||||||

这里是旋转开始

07-27 08:32:27.757: I/MainActivity(21285):  
07-27 08:32:27.789: I/MainActivity(21285):
07-27 08:32:27.789: I/MainActivity(21285): ***********STARTING APP*****************
07-27 08:32:27.789: I/MainActivity(21285): onCreate
07-27 08:32:27.789: I/MainActivity(21285):
07-27 08:32:27.890: I/StackOPreview(21285): in constructor
07-27 08:32:27.890: V/StackOPreview(21285): holder: android.view.SurfaceView$3@40566d20
07-27 08:32:27.890: V/StackOPreview(21285): this: com.chex.camera.StackOPreview@40566930
07-27 08:32:27.898: I/MainActivity(21285): onCreate finished
07-27 08:32:27.898: I/MainActivity(21285):
07-27 08:32:27.898: I/MainActivity(21285): ||||||||||||||||||| ON RESUME |||||||||||||||||||


HERE IS WHERE surfaceCreated SHOULD BE CALLED

07-27 08:32:27.898: I/MainActivity(21285):
07-27 08:32:27.945: I/MainActivity(21285):
07-27 08:32:27.945: I/MainActivity(21285): ||||||||||||||||||| ON PAUSE |||||||||||||||||||
07-27 08:32:27.945: I/MainActivity(21285):
07-27 08:32:27.968: I/StackOPreview(21285): onPause
07-27 08:32:27.968: I/MainActivity(21285): releasing camera in onPause
07-27 08:32:28.562: E/MainActivity(21285): onStop

Launcher 调用 Main

public class MainActivity extends Activity implements Constants

{

private static final String TAG = "MainActivity";

// CameraView variables
Camera camera;

boolean isPreviewRunning = false;

StackOPreview preview;

PhotoSaver photoSaver = null;

LayoutInflater controlInflater = null;

// first rear facing camera
int defaultCameraId;

// can't put big byte array in an Intent so keep a reference. This may not
// survive pauses.
private static byte[] currentPhoto = null;

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Log.i(TAG, " ");
Log.i(TAG, "***********STARTING APP*****************");

Log.i(TAG, "onCreate");

Log.i(TAG, " ");

getWindow().setFormat(PixelFormat.TRANSLUCENT);

requestWindowFeature(Window.FEATURE_NO_TITLE);

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);

// Find the total number of cameras available
int numberOfCameras = Camera.getNumberOfCameras();

// Find the ID of the default camera. This assumes the FACING BACK
// camera is default. probably burns us sometime.
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
defaultCameraId = i;
}
}

camera = Camera.open(defaultCameraId);
preview = new StackOPreview(this, camera);
setContentView(preview);

Log.i(TAG, "onCreate finished");

}

protected void onResume() {

super.onResume();

Log.i(TAG, " ");
Log.i(TAG, "||||||||||||||||||| ON RESUME |||||||||||||||||||");
Log.i(TAG, " ");

if (camera == null) {
// camera is rarely null in onResume. Either app was destroyed then
// recreated because a long time passed, or app was just paused and
// camera is still valid.
camera = Camera.open(defaultCameraId);

// July 24, 2013 sometimes preview is black - suspect it doesn't
// have a camera
preview.onResume(camera);

Log.i(TAG, "OPENING camera in onResume");
}

}

protected void onPause() {
super.onPause();

Log.i(TAG, " ");
Log.i(TAG, "||||||||||||||||||| ON PAUSE |||||||||||||||||||");
Log.i(TAG, " ");

// Release camera when activity paused
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;

preview.onPause();

Log.i(TAG, " releasing camera in onPause");
}

// close the database
Context context = getApplicationContext();
DatabaseHelper databaseHelper = DatabaseHelper.getInstance(context);
databaseHelper.close();
}

protected void onStop() {
Log.e(TAG, "onStop");
super.onStop();

Log.i(TAG, " ");
Log.i(TAG, "||||||||||||||||||| ON STOP |||||||||||||||||||");
Log.i(TAG, " ");

// close the database
Context context = getApplicationContext();
DatabaseHelper databaseHelper = DatabaseHelper.getInstance(context);
databaseHelper.close();

finish();
}

/** takes the picture */
public void onClick(View arg0) {
Log.e(TAG, "in CameraView.onClick");
camera.takePicture(null, null, photoSaver);

}

/**
* @return the currentPhoto
*/
public static byte[] getCurrentPhoto() {
return currentPhoto;
}

/**
* @param currentPhoto
* the currentPhoto to set
*/
public void setCurrentPhoto(byte[] currentPhoto) {
this.currentPhoto = currentPhoto;
}
}

预览代码:

   public class StackOPreview extends SurfaceView implements
SurfaceHolder.Callback {

private SurfaceHolder mHolder;
public Camera mCamera;

private static boolean DEBUGGING = true;
private static final String LOG_TAG = "StackOPreview";
private static final String CAMERA_PARAM_ORIENTATION = "orientation";
private static final String CAMERA_PARAM_LANDSCAPE = "landscape";
private static final String CAMERA_PARAM_PORTRAIT = "portrait";
protected Activity mActivity;

protected List<Camera.Size> previewSizeList = null;

protected Camera.Size previewSize = null;

public StackOPreview(Context context, Camera camera) {
super(context);

Log.i(LOG_TAG,"in constructor");

mActivity = (Activity) context;
mCamera = camera;

// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);

Log.v(LOG_TAG,"holder: "+mHolder);
Log.v(LOG_TAG,"this: "+ this);

// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}

public void surfaceCreated(SurfaceHolder holder) {
Log.i(LOG_TAG, "surfaceCreated");
// The Surface has been created, now tell the camera where to draw the
// preview.
try {

if (mCamera != null) {

setRotationAndResolution();

mCamera.setPreviewDisplay(holder);
mCamera.startPreview();

} else {
Log.d(LOG_TAG, " camera is null");
}
} catch (IOException e) {
Log.d("CameraView",
"Error setting camera preview: " + e.getMessage());
}
}

public void surfaceDestroyed(SurfaceHolder holder) {
Log.i(LOG_TAG, "surfaceDestroyed");
// empty. Take care of releasing the Camera preview in your activity.
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.i(LOG_TAG, "surfaceChanged");
// 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) {
Log.d(LOG_TAG, " mHolder is null");
// preview surface does not exist
return;
}

if (mCamera == null) {
Log.d(LOG_TAG, " camera is null");

return;
}

// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
Log.e(LOG_TAG, "failed to stopPreview because " + e, e);
}

// start preview with new settings
try {
setRotationAndResolution();

mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();

} catch (Exception e) {
Log.d("CameraView", "Error starting camera preview: " + e, e);
}
}

public void onPause() {
Log.i(LOG_TAG, "onPause");
if (null == mCamera) {
return;
}

mCamera = null;

// try releasing
mHolder.removeCallback(this);
}

// added July 24 2013.
/**
* Rarely called because camera is rarely null in MainActivity's onResume().
* Either app was destroyed then recreated because a long time passed, or
* app was just paused and camera is still valid. Occasionally I see a black
* screen after sleeping for a while so I added this method to try to fix
* it.
*/
public void onResume(Camera camera) {
Log.i(LOG_TAG, "onResume");
mCamera = camera;
}

private void setRotationAndResolution() {
final int width = getWidth();
final int height = getHeight();

Log.i(LOG_TAG, "view width: " + width + " height: " + height);

if (height > width) {
// PORTRAIT

Log.i(LOG_TAG, "portrait mode so rotate camera preview");

Context context = getContext();

int portraitOrientation = CameraSettings
.getPortraitPreviewOrientation(context);

int portraitRotation = CameraSettings
.getPortraitPictureRotation(context);

try {
// THis line fixed the preview orientation. seems to
// have to be called before setPreviewDisplay()
mCamera.setDisplayOrientation(portraitOrientation);

Camera.Parameters parameters = mCamera.getParameters();

// this line fixes the recorded image's orientation
parameters.setRotation(portraitRotation);

previewSize = getOptimalPreviewSize();

parameters
.setPreviewSize(previewSize.width, previewSize.height);

mCamera.setParameters(parameters);
} catch (Exception e) {
Log.e(LOG_TAG, "portrait preview settings failed: " + e, e);
Log.e(LOG_TAG, " orientation: " + portraitOrientation);
Log.e(LOG_TAG, " rotation: " + portraitRotation);
Log.e(LOG_TAG, " ");
}

} else {
// LANDSCAPE

Log.i(LOG_TAG, " landscape mode");

int landscapeOrientation = 0;
int landscapeRotation = 0;

try {
Context context = getContext();
landscapeOrientation = CameraSettings
.getLandscapePreviewOrientation(context);
landscapeRotation = CameraSettings
.getLandscapePictureRotation(context);

mCamera.setDisplayOrientation(landscapeOrientation);

previewSize = getOptimalPreviewSize();

// THis line fixed the preview orientation. seems to
// have to be called before setPreviewDisplay()
mCamera.setDisplayOrientation(landscapeOrientation);

Camera.Parameters parameters = mCamera.getParameters();

// this line fixes the recorded image's orientation
parameters.setRotation(landscapeRotation);

parameters
.setPreviewSize(previewSize.width, previewSize.height);

mCamera.setParameters(parameters);
} catch (Exception e) {
Log.e(LOG_TAG, "landscape preview settings failed: " + e, e);
Log.e(LOG_TAG, " orientation: " + landscapeOrientation);
Log.e(LOG_TAG, " rotation: " + landscapeRotation);
Log.e(LOG_TAG, " ");
}
}

}

private Size getOptimalPreviewSize() {

// if list isn't retrieved yet, then get it
if (previewSizeList == null) {
previewSizeList = mCamera.getParameters()
.getSupportedPreviewSizes();

}

int width = getWidth();

int height = getHeight();

Log.i(LOG_TAG, "setting View measured dimensions to width: " + width
+ " height: " + height);

final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) width / height;

Size optimalSize = null;
double minDiff = Double.MAX_VALUE;

int targetHeight = height;

// Try to find an size match aspect ratio and size
for (Size size : previewSizeList) {
//Log.v(LOG_TAG, " width: " + size.width + " height: "
// + size.height);

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 : previewSizeList) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}

Log.i(LOG_TAG, "optimal preview width: " + optimalSize.width
+ " height: " + optimalSize.height);

return optimalSize;
}

最佳答案

我使用来自 Commonsware 的 Mark Murphy 的提示解决了这个问题。我在主要 Activity 中将预览创建移动到 onResume() 。另外,我删除了 onStop() 中的 finish() 调用。这是 MainActivity 中的 onCreate() 和 onResume():

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Find the total number of cameras available
int numberOfCameras = Camera.getNumberOfCameras();

// Find the ID of the default camera. This assumes the FACING BACK
// camera is default. probably burns us sometime.
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
defaultCameraId = i;
}
}
}

protected void onResume() {

super.onResume();

Log.i(TAG, " ");
Log.i(TAG, "||||||||||||||||||| ON RESUME |||||||||||||||||||");
Log.i(TAG, " ");

getWindow().setFormat(PixelFormat.TRANSLUCENT);

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);

camera = Camera.open(defaultCameraId);
preview = new StackOPreview(this, camera);
setContentView(preview);

// *** new control layer that contains the TakePicture button ***
controlInflater = LayoutInflater.from(getBaseContext());

viewControl = controlInflater.inflate(R.layout.control_preview, null);

LayoutParams layoutParamsControl = new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);

this.addContentView(viewControl, layoutParamsControl);

photoSaver = new PhotoSaver(this);

buttonTakePicture = (ImageButton) findViewById(R.id.takepicture);

buttonTakePicture.setOnClickListener(new Button.OnClickListener() {

@Override
public void onClick(View v) {
Log.v(TAG,
"in Take Picture button on click, launching photSaver");
camera.takePicture(null, null, photoSaver);
}
});

// table button
Button tableButton = (Button) findViewById(R.id.display_table);

TableButtonListener tableButtonListener = new TableButtonListener(this);
tableButton.setOnClickListener(tableButtonListener);
}

关于android - 旋转后未调用 surfaceCreated(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17898200/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com