所以我跟着Android开发人员构建了一个摄像头应用程序示例,让我的摄像头活动正常运行。然而,当我去另一个活动然后点击后退按钮我发生了崩溃,因为相机在表面创建的表面视图中为空。有人可以解释这个错误是如何发生的。谢谢!
**活动
public class PhotoCaptureActivity extends AppCompatActivity implements View.OnClickListener{
public static final String TAG = "PhotoCaptureActivity";
CameraPreview mPreviewScreen;
Button mCaptureButton;
ImageView mPreviewThumbnail;
TextView mPhotoActionLabel;
TextView mImageLogText;
Camera mCamera;
Camera.PictureCallback mPicture;
ArrayList<Bitmap> mPictures = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo_capture);
getSupportActionBar().hide();
mCaptureButton = (Button) findViewById(R.id.button_capture);
mPreviewThumbnail = (ImageView) findViewById(R.id.thumb_nail_image);
mPhotoActionLabel = (TextView) findViewById(R.id.photo_action_text);
mImageLogText = (TextView) findViewById(R.id.image_log);
mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
BitmapFactory.Options scalingOptions = new BitmapFactory.Options();
scalingOptions.inSampleSize = camera.getParameters().getPictureSize().width / mPreviewThumbnail.getMeasuredWidth();
final Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length, scalingOptions);
mPictures.add(bmp);
mPreviewThumbnail.setImageBitmap(bmp);
mPreviewThumbnail.setVisibility(ImageView.VISIBLE);
mCamera.startPreview();
mPhotoActionLabel.setText(getString(R.string.done));
}
};
mCaptureButton.setOnClickListener(this);
mPhotoActionLabel.setOnClickListener(this);
mImageLogText.setOnClickListener(this);
}
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
e.printStackTrace();
}
return c; // returns null if camera is unavailable
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button_capture:
mCamera.takePicture(null, null, mPicture);
break;
case R.id.photo_action_text:
if (mPhotoActionLabel.getText().toString().equalsIgnoreCase(getString(R.string.cancel)))
finish();
else {
Intent photoReviewIntent = new Intent(this,PhotoReviewActivity.class);
startActivity(photoReviewIntent);
}
break;
case R.id.image_log:
Intent imageLogIntent = new Intent(this,ImageLogActivity.class);
startActivity(imageLogIntent);
break;
}
}
@Override
public void onPause(){
super.onPause();
mCamera.stopPreview();
mCamera.release();
}
@Override
public void onResume(){
super.onResume();
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
mCamera = getCameraInstance();
if (mCamera != null){
mPreviewScreen = new CameraPreview(this,mCamera);
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.camera_preview);
frameLayout.addView(mPreviewScreen);
}
else
Toast.makeText(this, R.string.failed_to_open_camera, Toast.LENGTH_LONG).show();
}
else
Toast.makeText(this, R.string.no_camera_available, Toast.LENGTH_LONG).show();
}
}
**预览屏幕java类
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
this.mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
Log.i("Error starting camera", e.getLocalizedMessage());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.i("Error starting camera", e.getLocalizedMessage());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//Handeled in activity
}
}
答案 0 :(得分:1)
在onResume()
中,旧的 mPreviewScreen 可能仍然存在,并会导致问题。请考虑将以下内容添加到onPause()
:
if (mPreviewScreen != null) {
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.camera_preview);
frameLayout.removeView(mPreviewScreen);
mPreviewScreen = null;
}
mCamera = null;