首先自定义一个继承自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. java设计模式、框架、架构、平台之间的关系

        设计模式<框架<架构<平台,从复用角度讲,设计模式是代码级复用.框架是模块级复用.架构是系统级复用.平台是企业应用级复用. 1.设计模式 为什么要先说设计模式?因为设计模式在 ...

  2. systemd初始化进程(转)

    Systemd初始化进程 Linux操作系统开机过程首先从BIOS开始→进入"Boot Loader"→加载内核→内核的初始化→启动初始化进程,初始化进程作为系统第一个进程,它需要 ...

  3. 题解 P1280 【尼克的任务】

    传送门 f[i]表示i~n的最长空闲时间: 如果当前无任务就休息一秒(f[i]=f[i+1]+1): 否则f[i]=max(f[i],f[i+当前工作时间]); 用结构体来记录,我们对于每一个时刻开一 ...

  4. 从多个textarea中随机选取一个内容

    <div id="IMContentTest"> <textarea name="IMContent" class="IMClass ...

  5. sass安装更新及卸载方法

    在 Windows 平台下安装 Ruby 需要先有 Ruby 安装包,大家可以到 Ruby 的官网(http://rubyinstaller.org/downloads)下载对应需要的 Ruby 版本 ...

  6. windows平台下MongoDB安装和环境搭建

    下载安装包或者压缩包 添加db存储和日志存储文件夹 添加服务.配置环境变量.启动Mongo 本例:安装路径:D:Program Files/MongoDB 配置文件的路径:D:MongoDB 一.安装 ...

  7. java算法面试题:有数组a[n],用java代码将数组元素顺序颠倒

    package com.swift; import java.util.ArrayList; import java.util.Collections; import java.util.List; ...

  8. SQL数据库从高版本导入低版本

    1. 打开高版本数据库右键–>任务–>生成脚本–>高级–>选择脚本兼容的版本(也就是低版本)–>拉倒最下面选择架构和数据 2. 在低版本里面,先新建一个数据库,名称要和脚 ...

  9. 四、Shell 数组

    Shell 数组 数组中可以存放多个值.Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 PHP 类似). 与大部分编程语言类似,数组元素的下标由0开始. She ...

  10. 配置管理-SpringCloudConfig

    1.搭建配置管理服务 添加依赖 <dependencies> <dependency> <groupId>org.springframework.cloud< ...