所以我有一个非常基本的相机实现。 我的目标是每隔10秒自动在前后摄像头之间切换,直到点击按钮停止。
这是我的MainActivity
:
public class MainActivity extends Activity {
private Camera mCamera = null;
private CameraView mCameraView = null;
private CountDownTimer countDownTimer;
private int mCamId = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startCam();
if(mCamera != null) {
mCameraView = new CameraView(this, mCamera);//create a SurfaceView to show camera data
FrameLayout camera_view = (FrameLayout)findViewById(R.id.camera_view);
camera_view.addView(mCameraView);//add the SurfaceView to the layout
}
//btn to close the application
ImageButton imgClose = (ImageButton)findViewById(R.id.imgClose);
imgClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
System.exit(0);
}
});
}
private void startCam() {
try{
//you can use open(int) to use different cameras
mCamId = mCamId == 0 ? 1 : 0;
mCamera = Camera.open(mCamId);
switchCam();
} catch (Exception e){
Log.d("ERROR", "Failed to get camera: " + e.getMessage());
}
}
private void switchCam() {
//10 seconds
countDownTimer = new CountDownTimer(10000, 1000) {
@Override
public void onTick(long l) {
Log.d(TAG, l + " left");
}
@Override
public void onFinish() {
cleanup();
startCam();
}
}.start();
}
public void cleanup() {
Log.i(TAG, "Switching Camera");
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
}
这是我的CameraView
课程:
public class CameraView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraView(Context context, Camera camera){
super(context);
mCamera = camera;
mCamera.setDisplayOrientation(90);
//get the holder and set this class as the callback, so we can get camera data here
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try{
//when the surface is created, we can set the camera to draw images in this surfaceholder
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("ERROR", "Camera error on surfaceCreated " + e.getMessage());
}
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
//before changing the application orientation, you need to stop the preview, rotate and then start it again
if(mHolder.getSurface() == null)//check if the surface is ready to receive camera data
return;
try{
mCamera.stopPreview();
} catch (Exception e){
//this will happen when you are trying the camera if it's not running
}
//now, recreate the camera preview
try{
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("ERROR", "Camera error on surfaceChanged " + e.getMessage());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
//our app has only one screen, so we'll destroy the camera in the surface
//if you are unsing with more screens, please move this code your activity
mCamera.stopPreview();
mCamera.release();
}
第一台相机启动没有问题。然而,界面在第二相机的切换时冻结成静态图像,即在10秒之后。我无法解决它。我错在哪里?
最小,完整,可验证和可编制的代码:LINK
答案 0 :(得分:-1)
您目前的工作:
在onCreate方法中,您在startCam()之后更新FrameLayout。
if(mCamera != null) {
mCameraView = new CameraView(this, mCamera);//create a SurfaceView to show camera data
FrameLayout camera_view = (FrameLayout)findViewById(R.id.camera_view);
camera_view.addView(mCameraView);//add the SurfaceView to the layout
}
当相机切换时,释放旧相机并打开新相机,但您忘记也更新FrameLayout。所以问题不在于什么"冻结"但是在GUI中没有更新到新相机的切换。
如何解决问题:
在方法switchCam()中,您还需要更新FrameLayout,就像在onCreate方法中一样。
switchCam()方法的一个工作示例如下:
private void switchCam() {
//10 seconds
countDownTimer = new CountDownTimer(10000, 1000) {
@Override
public void onTick(long l) {
Log.d(TAG, l + " left");
}
@Override
public void onFinish() {
cleanup();
startCam();
if(mCamera != null) {
mCameraView = new CameraView(getApplicationContext(), mCamera);//create a SurfaceView to show camera data
FrameLayout camera_view =
(FrameLayout)findViewById(R.id.camera_view);
if(( camera_view).getChildCount() > 0)
{
camera_view.removeAllViews();
}
camera_view.addView(mCameraView);//add the SurfaceView to the layout
}
}
}.start();
}
如果仅此问题无法解决您的问题,您还可以尝试以下方法:
将AndroidManifest hardware.camera中的uses-feature更改为hardware.camera2,因为不推荐使用hardware.camera。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="in.harjot.andorid.cameraswap">
...
<uses-feature android:name="android.hardware.camera2" />
...
</manifest>
在我的Nexus5X上,该应用程序似乎也存在权限问题,所以我在onCreate方法中添加了以下内容:在调用startCam()之前(没有这个我实际上根本看不到任何内容):
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
1);
}
startCam();
...
}