我可以使用 TextureView 正确显示相机视频的预览:
package com.example.camerasurfacetexture;
import java.io.IOException;
import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.widget.FrameLayout;
public class MainActivity extends Activity implements SurfaceTextureListener
{
private Camera mCamera = null;
private TextureView mTextureView = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
setContentView(mTextureView);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
int height)
{
Log.i("onSurfaceTextureAvailable", "onSurfaceTextureAvailable");
mCamera = Camera.open();
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width, previewSize.height, Gravity.CENTER));
try
{
mCamera.setPreviewTexture(surface);
}
catch (IOException t)
{
}
mCamera.startPreview();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height)
{
// Ignored, the Camera does all the work for us
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface)
{
Log.i("onSurfaceTextureDestroyed", "onSurfaceTextureDestroyed");
mCamera.stopPreview();
mCamera.release();
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface)
{
// Update your view here!
}
}
并使用 SurfaceView:
package com.example.cameratest;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class MainActivity extends Activity
{
private SurfaceView preview = null;
private SurfaceHolder previewHolder = null;
private Camera camera = null;
private boolean inPreview = false;
private boolean cameraConfigured = false;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
preview = (SurfaceView) findViewById(R.id.cpPreview);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void onResume()
{
super.onResume();
camera = Camera.open();
startPreview();
}
@Override
public void onPause()
{
if (inPreview)
{
camera.stopPreview();
}
camera.release();
camera = null;
inPreview = false;
super.onPause();
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters)
{
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes())
{
if (size.width <= width && size.height <= height)
{
if (result == null)
{
result = size;
}
else
{
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea)
{
result = size;
}
}
}
}
return (result);
}
private void initPreview(int width, int height)
{
if (camera != null && previewHolder.getSurface() != null)
{
try
{
camera.setPreviewDisplay(previewHolder);
}
catch (Throwable t)
{
Log.e("PreviewDemo-surfaceCallback",
"Exception in setPreviewDisplay()", t);
Toast.makeText(MainActivity.this, t.getMessage(),
Toast.LENGTH_LONG).show();
}
if (!cameraConfigured)
{
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null)
{
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
cameraConfigured = true;
}
}
}
}
private void startPreview()
{
if (cameraConfigured && camera != null)
{
camera.startPreview();
inPreview = true;
}
}
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback()
{
public void surfaceCreated(SurfaceHolder holder)
{
// no-op -- wait until surfaceChanged()
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
initPreview(width, height);
startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder)
{
// no-op
}
};
}
但如果我尝试同时做这两个:
package com.example.multiplecamerapreviewtest;
import java.io.IOException;
import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.widget.FrameLayout;
import android.widget.Toast;
public class MainActivity extends Activity implements SurfaceTextureListener
{
private SurfaceView svPreview = null;
private SurfaceHolder previewHolder = null;
private Camera mCamera = null;
private boolean inPreview = false;
private boolean cameraConfigured = false;
private TextureView tvPreview = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
svPreview = (SurfaceView) findViewById(R.id.svPreview);
previewHolder = svPreview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// mTextureView = new TextureView(this);
tvPreview = (TextureView) findViewById(R.id.tvPreview);
tvPreview.setSurfaceTextureListener(this);
// setContentView(mTextureView);
}
@Override
public void onResume()
{
super.onResume();
mCamera = Camera.open();
startPreview();
}
@Override
public void onPause()
{
if (inPreview)
{
mCamera.stopPreview();
}
mCamera.release();
mCamera = null;
inPreview = false;
super.onPause();
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters)
{
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes())
{
if (size.width <= width && size.height <= height)
{
if (result == null)
{
result = size;
}
else
{
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea)
{
result = size;
}
}
}
}
return (result);
}
private void initPreview(int width, int height)
{
if (mCamera != null && previewHolder.getSurface() != null)
{
try
{
mCamera.setPreviewDisplay(previewHolder);
}
catch (Throwable t)
{
Log.e("PreviewDemo-surfaceCallback",
"Exception in setPreviewDisplay()", t);
Toast.makeText(MainActivity.this, t.getMessage(),
Toast.LENGTH_LONG).show();
}
if (!cameraConfigured)
{
Camera.Parameters parameters = mCamera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null)
{
parameters.setPreviewSize(size.width, size.height);
mCamera.setParameters(parameters);
cameraConfigured = true;
}
}
}
}
private void startPreview()
{
if (cameraConfigured && mCamera != null)
{
mCamera.startPreview();
inPreview = true;
}
}
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback()
{
public void surfaceCreated(SurfaceHolder holder)
{
// no-op -- wait until surfaceChanged()
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
initPreview(width, height);
startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder)
{
// no-op
}
};
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
int height)
{
Log.i("onSurfaceTextureAvailable", "onSurfaceTextureAvailable");
mCamera = Camera.open();
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
tvPreview.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width, previewSize.height, Gravity.CENTER));
try
{
mCamera.setPreviewTexture(surface);
}
catch (IOException t)
{
}
mCamera.startPreview();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height)
{
// Ignored, the Camera does all the work for us
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface)
{
Log.i("onSurfaceTextureDestroyed", "onSurfaceTextureDestroyed");
mCamera.stopPreview();
mCamera.release();
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface)
{
// Update your view here!
}
}
调用 mCamera.setPreviewTexture() 时出现“无法连接到相机服务”异常。
根据文档(http://developer.android.com/reference/android/hardware/Camera.html#setPreviewDisplay%28android.view.SurfaceHolder%29),这是预期的行为:
setPreviewDisplay()
Setting a preview surface will un-set any preview surface texture that was set via setPreviewTexture(SurfaceTexture).
(反之亦然)。我能做些什么来让这两者同时显示吗?