首先自定义一个继承自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时调用
*/
@Override
public 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();
} @Override
public void surfaceCreated(SurfaceHolder holder) {
if(mCamera == null){
return;
}
try {
mCamera.setPreviewDisplay(surfaceHolder);
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview(); } @Override
public 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;//当前打开的摄像头标记
@Override
protected 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() {
@Override
public void onClick(View v) {
try {
changeCamera();
} catch (IOException e) {
// TODO Auto-generated catch block
e.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="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/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" > <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/switchcamera" /> <com.example.cameratest.CameraView
android: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,不然显示的方向不对。

如果有可以优化的地方,望各位大侠指导,谢谢。

android实现前置后置摄像头相互切换的更多相关文章

  1. win 10 禁用后置摄像头

    2.双摄像头电脑,甄别时默认开启的是后置摄像头,识别不到人脸. (1)更换设备参加甄别: (2)自行调整:停用电脑后置摄像头,停用后甄别时会默认调取前置摄像头: 以下操作适用于Windows surf ...

  2. spring 切面 前置后置通知 环绕通知demo

    环绕通知: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http:// ...

  3. AOP 环绕通知 集成了前置 后置 返回通知等功能

    AOP 环绕通知 集成了前置 后置 返回通知等功能

  4. uwp之拍照(使用后置摄像头)

    参考:wp8.1之拍照(获取焦点,使用后置摄像头) uwp开启摄像头要借助CaptureElement呈现来自捕获设备(如照相机或网络摄像机)的流.今天讲讲如何打开摄像头,获取焦点,以及拍照.废话不多 ...

  5. wp8.1之拍照(获取焦点,使用后置摄像头)

    wp8.1 没有像wp8一样直接用启动器开启摄像头,他要开启摄像头要借助CaptureElement呈现来自捕获设备(如照相机或网络摄像机)的流.今天讲讲如何打开摄像头,获取焦点,以及拍照.废话不多说 ...

  6. pytest_前置后置

    今天总结下pytest,pytest简直就是python自动化中的高富帅,各种操作,哈哈 这次总结主要涉及到了以下几点: 1.unittest中的setUp.tearDown.setUpClass.t ...

  7. Spring Bean前置后置处理器的使用

    Spirng中BeanPostProcessor和InstantiationAwareBeanPostProcessorAdapter两个接口都可以实现对bean前置后置处理的效果,那这次先讲解一下B ...

  8. unittest的前置后置,pytest的fixture和共享机制conftest.py

    Unittest setUp/tearDown setUp当中得到的变量,用self.xxx = value传递给测试用例 setUpClass/tearDownClass setupClass当中得 ...

  9. C: printf参数执行顺序与前置后置自增自减的影响

    起源: 今天在了解副作用side-effect的过程中,看到了下面的网页,把我带到了由printf引起的一系列问题,纠结了一整天,勉强弄懂. 第一个代码没什么好解释的.而第二个printf(" ...

随机推荐

  1. 【挖坑】2019年JAVA安全总结:SQL注入——新项目的开发与老项目的修复

    如何在项目中有效的防止SQL注入 写给需要的人,所有的问题源自我们的不重视. 本章略过"什么是SQL注入","如何去利用SQL注入"的讲解,仅讲如何去防御 PS ...

  2. Problem C: 动态规划基础题目之数字三角形

    Problem C: 动态规划基础题目之数字三角形 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 208  Solved: 139[Submit][Sta ...

  3. opencv anaconda

    from: http://blog.csdn.net/fairylrt/article/details/43560525 Anaconda是一个python的一个包装,或者不单单是这样.你可以认为An ...

  4. axiospost请求向后端提交数据

    Axios向后端提交数据容易接收不到原因是传参方式是request payload,参数格式是json,而并非用的是form传参,所以在后台用接收form数据的方式接收参数就接收不到了.post表单请 ...

  5. Wordpress菜单函数wp_nav_menu各参数详解及示例

    Wordpress菜单函数wp_nav_menu各参数详解及示例   注册菜单 首先要注册菜单,将以下函数添加至function.php函数里   register_nav_menus(array( ...

  6. jqweui 中的tabbar导航

    最近做微信的服务号项目,用的jqweui作为主要的ui,但是对于用惯了ele ui的开发者来说,文档貌似有点不友好.真是很让人头疼! 所以结合着自己做的项目,随便写一点东西. 比如说,tabbar导航 ...

  7. node 发送邮件demo (QQ邮箱)

    nodemailer是nodejs中的邮件发送模块,本文使用的版本为2.5.0 --下载模块 npm install nodemailer npm下载模块后,在项目中引入就可以使用: var node ...

  8. windows_Bat_Scripts查看系统IP-更改regedit-更新系统补丁

    1.1    脚本名称 Update_patch.bat 1.2    脚本代码 @echo off :menu cls mode con cols=48 lines=27 & color 0 ...

  9. confirm() 方法用于显示一个带有指定消息和 OK 及取消按钮的对话框。系统自带提示

    W3C地址:::::::   http://www.w3school.com.cn/jsref/met_win_confirm.asp http://www.w3school.com.cn/tiy/t ...

  10. 快速排序,对于相同元素的优化,c++

    #include<iostream>using namespace std; void middl(int &p,int &q,int &r)//找枢轴,然后把枢轴 ...