首先自定义一个继承自SurfaceView并且实现了SurfaceHolder.Callback接口的组件:
public class CameraView extends SurfaceView implements Callback {private SurfaceHolder surfaceHolder;private Camera mCamera;public CameraView(Context context, AttributeSet attrs) {super(context, attrs);}public void init(Camera camera){surfaceHolder = getHolder();surfaceHolder.addCallback(this);mCamera = camera;}/*** 初始化SurfaceView时调用一次,另外更改surface或者onpause->onresume时调用*/@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {if(holder.getSurface() == null || mCamera == null){return;}mCamera.stopPreview();try {mCamera.setPreviewDisplay(surfaceHolder);} catch (IOException e) {// TODO Auto-generated catch block e.printStackTrace();}mCamera.startPreview();}@Overridepublic void surfaceCreated(SurfaceHolder holder) {if(mCamera == null){return;}try {mCamera.setPreviewDisplay(surfaceHolder);} catch (IOException e) {e.printStackTrace();}mCamera.startPreview();}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {// TODO Auto-generated method stub }}
检查设备是否有摄像头:
private boolean checkCamera(){return MainActivity.this.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);}
标记前置,后置摄像头,以及当前打开的摄像头,并且首先默认打开前置摄像头,监听Button的click事件,切换摄像头:
public class MainActivity extends Activity {private Button button;private Camera camera;private CameraView cameraView;private static final int FRONT = 1;//前置摄像头标记private static final int BACK = 2;//后置摄像头标记private int currentCameraType = -1;//当前打开的摄像头标记 @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if(!checkCamera()){MainActivity.this.finish();}try {camera = openCamera(FRONT);} catch (Exception e) {e.printStackTrace();}button = (Button)findViewById(R.id.button);button.setOnClickListener(new Button.OnClickListener() {@Overridepublic void onClick(View v) {try {changeCamera();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}});cameraView = (CameraView)findViewById(R.id.cameraview);cameraView.init(camera);}/*** @return 摄像头是否存在*/private boolean checkCamera(){return MainActivity.this.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);}@SuppressLint("NewApi")private Camera openCamera(int type){int frontIndex =-1;int backIndex = -1;int cameraCount = Camera.getNumberOfCameras();CameraInfo info = new CameraInfo();for(int cameraIndex = 0; cameraIndex<cameraCount; cameraIndex++){Camera.getCameraInfo(cameraIndex, info);if(info.facing == CameraInfo.CAMERA_FACING_FRONT){frontIndex = cameraIndex;}else if(info.facing == CameraInfo.CAMERA_FACING_BACK){backIndex = cameraIndex;}}currentCameraType = type;if(type == FRONT && frontIndex != -1){return Camera.open(frontIndex);}else if(type == BACK && backIndex != -1){return Camera.open(backIndex);}return null;}private void changeCamera() throws IOException{camera.stopPreview();camera.release();if(currentCameraType == FRONT){camera = openCamera(BACK);}else if(currentCameraType == BACK){camera = openCamera(FRONT);}camera.setPreviewDisplay(cameraView.getHolder());camera.startPreview();}}
布局文件:
<RelativeLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity" ><Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/switchcamera" /><com.example.cameratest.CameraViewandroid:id="@+id/cameraview"android:layout_below="@id/button"android:layout_width="fill_parent"android:layout_height="fill_parent"/></RelativeLayout>
当然,首先得申明权限跟软硬件环境:
<uses-permission android:name="android.permission.CAMERA"/><uses-feature android:name="android.hardware.camera"/>
最好把activity的screenOrientation设置为landscape,不然显示的方向不对。
如果有可以优化的地方,望各位大侠指导,谢谢。