前言:相机应用预览界面切换到后台后,通常会释放相机资源,这样其他应用能够及时打开摄像头。我的做法是在Acitivity生命周期的onStart()时打开摄像头,在onStop()释放摄像头资源。这样做存在一个小问题,预览界面切换后台再切前台,此时预览画面卡住。
原因:onStop()时,SurfaceView或TextureView没有销毁,所以重新打开摄像头时,view的生命周期不会重新执行,也就无法刷新。
解决方法:SurfaceView或TextureView通过new实例化,而不是在布局中定义。并且在onStart() 通过addview方式把view加到布局中,在onStop()时通过removeView()方式移除view。
具体实现,布局定义layout/activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/preview_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- add or remove textureview on activity-->
</LinearLayout>
<!-- others view -->
</RelativeLayout>
Activity中
private TextureView textureView;
private LinearLayout textureViewParent;
private Camera camera;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureViewParent = findViewById(R.id.preview_parent);
textureView = new TextureView(this);
LinearLayout.LayoutParams lp = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
textureView.setLayoutParams(lp);
}
@Override
protected void onStart() {
super.onStart();
textureViewParent.addView(textureView);
openCamera(textureView, 0);
}
@Override
protected void onStop() {
super.onStop();
textureViewParent.removeView(textureView);
if (camera != null) {
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
}
}
private void openCamera(final TextureView textureView, final int cameraId) {
if (textureView == null || cameraId < 0) {
return;
}
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
try {
camera = Camera.open(cameraId);
camera.setPreviewTexture(surfaceTexture);
camera.startPreview();
} catch (IOException localIOException) {
Log.e(TAG, "onSurfaceTextureAvailable open camera localIOException cameraId=" + cameraId + ", error=" + localIOException.getMessage(), localIOException);
} catch (Exception e) {
Log.e(TAG, "onSurfaceTextureAvailable open camera cameraId=" + cameraId + ", error=" + e.getMessage(), e);
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
});
}