Android切换前后置摄像头并录制视频
项目需要对微信的视频模块也看了一下,在此就对这块进行了一个开发。首先给出效果图
首先给出java代码
/** * RecordActivity.java * 版权所有(C) 2013 * 创建:cuiran 2013-10-15 下午3:20:45 */ package com.app931.oa.activity.video; import java.io.IOException; import java.util.List; import com.app931.oa.R; import com.app931.oa.util.LogsUtil; import com.app931.oa.util.SupportedSizesReflect; import android.app.Activity; import android.content.Context; import android.graphics.PixelFormat; import android.hardware.Camera; import android.hardware.Camera.CameraInfo; import android.hardware.Camera.Size; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnBufferingUpdateListener; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaRecorder; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.Display; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.view.SurfaceHolder.Callback; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; /** * TODO * @author cuiran * @version 1.0.0 */ public class RecordActivity extends Activity implements Callback,MediaPlayer.OnPreparedListener, OnBufferingUpdateListener, OnCompletionListener { private static final String TAG="RecordActivity"; private String videoPath="/sdcard/love.3gp"; private MediaRecorder mediarecorder;// 录制视频的类 private MediaPlayer mediaPlayer;//播放视频的类 private SurfaceView surfaceview;// 显示视频的控件 private Camera camera; //实现这个接口的Callback接口 private SurfaceHolder surfaceHolder; /** * 是否正在录制true录制中 false未录制 */ private boolean isRecord=false; public boolean isCameraBack=true; private ImageView recordIv; private ImageView recordPlayIv; private int mVideoWidth; private int mVideoHeight; int cameraCount = 0; private int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_video_record1); setTitleStr(""); // 选择支持半透明模式,在有surfaceview的activity中使用。 getWindow().setFormat(PixelFormat.TRANSLUCENT); initView(); } /** * TODO */ private void initView() { // TODO Auto-generated method stub surfaceview = (SurfaceView) this.findViewById(R.id.surfaceview); recordIv=(ImageView)findViewById(R.id.recordIv); recordPlayIv=(ImageView)findViewById(R.id.recordPlayIv); SurfaceHolder holder = surfaceview.getHolder();// 取得holder holder.addCallback(this); // holder加入回调接口 // setType必须设置,要不出错. holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } /** * 播放视频 * TODO * @param v */ public void playVideo(View v){ recordPlayIv.setVisibility(View.GONE); try { mediaPlayer=new MediaPlayer(); mediaPlayer.setDataSource(videoPath); mediaPlayer.setDisplay(surfaceHolder); mediaPlayer.prepareAsync(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } mediaPlayer.setOnBufferingUpdateListener(this); mediaPlayer.setOnCompletionListener(this); mediaPlayer.setOnPreparedListener(this); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); } /** * 开始录制/停止录制 * TODO * @param v */ public void recordVideo(View v){ if(isRecord){ isRecord=false; recordIv.setImageResource(R.drawable.video_recorder_start_btn_nor); recordPlayIv.setVisibility(View.VISIBLE); if (mediarecorder != null) { // 停止录制 mediarecorder.stop(); // 释放资源 mediarecorder.release(); mediarecorder = null; } if(camera!=null){ camera.release(); } }else{ isRecord=true; recordIv.setImageResource(R.drawable.video_recorder_recording_btn); recordPlayIv.setVisibility(View.GONE); mediarecorder = new MediaRecorder();// 创建mediarecorder对象 // // 从麦克风源进行录音 // mediarecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); // // 设置输出格式 // mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // // 设置编码格式 // mediarecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); /** * 设置竖着录制 */ if(camera!=null){ camera.release(); } if(cameraPosition==1){ camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);//打开摄像头 // camera = Camera.open(cameraPosition);//打开摄像头 // Camera.Parameters parameters = camera.getParameters(); // camera.setDisplayOrientation(90); // camera.setParameters(parameters); camera=deal(camera); mediarecorder.setOrientationHint(90);//视频旋转90度 }else{ camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);//打开摄像头 Camera.Parameters parameters = camera.getParameters(); camera.setDisplayOrientation(90); camera.setParameters(parameters); mediarecorder.setOrientationHint(270);//视频旋转90度 } camera.unlock(); mediarecorder.setCamera(camera); // 设置录制视频源为Camera(相机) mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 设置录制完成后视频的封装格式THREE_GPP为3gp.MPEG_4为mp4 mediarecorder .setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); // 设置录制的视频编码h263 h264 mediarecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置视频录制的分辨率。必须放在设置编码和格式的后面,否则报错 mediarecorder.setVideoSize(176, 144); // 设置录制的视频帧率。必须放在设置编码和格式的后面,否则报错 mediarecorder.setVideoFrameRate(20); mediarecorder.setPreviewDisplay(surfaceHolder.getSurface()); // 设置视频文件输出的路径 mediarecorder.setOutputFile(videoPath); try { // 准备录制 mediarecorder.prepare(); mediarecorder.start(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } protected void setTitleStr(String str) { TextView titleText = (TextView) findViewById(R.id.common_title_text); titleText.setText(str.trim()); Button left_button=(Button)findViewById(R.id.left_button); left_button.setVisibility(View.VISIBLE); left_button.setText("返回"); left_button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub back(); } }); Button right_button=(Button)findViewById(R.id.right_button); right_button.setVisibility(View.VISIBLE); right_button.setText(""); right_button.setBackgroundResource(R.drawable.btn_video_switch_bg); right_button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub cameraCount=Camera.getNumberOfCameras(); if(isCameraBack){ isCameraBack=false; }else{ isCameraBack=true; } // SurfaceHolder holder = surfaceview.getHolder();// 取得holder // holder.addCallback(RecordActivity.this); // holder加入回调接口 // LogsUtil.i(TAG, "cameraCount="+cameraCount); int cameraCount = 0; CameraInfo cameraInfo = new CameraInfo(); cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数 for(int i = 0; i < cameraCount; i++) { Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息 if(cameraPosition == 1) { //现在是后置,变更为前置 if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置 camera.stopPreview();//停掉原来摄像头的预览 camera.release();//释放资源 camera = null;//取消原来摄像头 camera = Camera.open(i);//打开当前选中的摄像头 try { deal(camera); camera.setPreviewDisplay(surfaceHolder);//通过surfaceview显示取景画面 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } camera.startPreview();//开始预览 cameraPosition = 0; break; } } else { //现在是前置, 变更为后置 if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置 camera.stopPreview();//停掉原来摄像头的预览 camera.release();//释放资源 camera = null;//取消原来摄像头 camera = Camera.open(i);//打开当前选中的摄像头 try { deal(camera); camera.setPreviewDisplay(surfaceHolder);//通过surfaceview显示取景画面 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } camera.startPreview();//开始预览 cameraPosition = 1; break; } } } } }); } /** * 返回 *<b>function:</b> *@author cuiran *@createDate 2013-8-20 下午2:22:48 */ public void back(){ finish(); } public Camera deal(Camera camera){ //设置camera预览的角度,因为默认图片是倾斜90度的 camera.setDisplayOrientation(90); Size pictureSize=null; Size previewSize=null; Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewFrameRate(5); //设置旋转代码 parameters.setRotation(90); // parameters.setPictureFormat(PixelFormat.JPEG); List<Size> supportedPictureSizes = SupportedSizesReflect.getSupportedPictureSizes(parameters); List<Size> supportedPreviewSizes = SupportedSizesReflect.getSupportedPreviewSizes(parameters); if ( supportedPictureSizes != null && supportedPreviewSizes != null && supportedPictureSizes.size() > 0 && supportedPreviewSizes.size() > 0) { //2.x pictureSize = supportedPictureSizes.get(0); int maxSize = 1280; if(maxSize > 0){ for(Size size : supportedPictureSizes){ if(maxSize >= Math.max(size.width,size.height)){ pictureSize = size; break; } } } WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); DisplayMetrics displayMetrics = new DisplayMetrics(); display.getMetrics(displayMetrics); previewSize = getOptimalPreviewSize( supportedPreviewSizes, display.getWidth(), display.getHeight()); parameters.setPictureSize(pictureSize.width, pictureSize.height); parameters.setPreviewSize(previewSize.width, previewSize.height); } camera.setParameters(parameters); return camera; } /* (non-Javadoc) * @see android.view.SurfaceHolder.Callback#surfaceChanged(android.view.SurfaceHolder, int, int, int) */ @Override public void surfaceChanged(SurfaceHolder holder, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub // 将holder,这个holder为开始在oncreat里面取得的holder,将它赋给surfaceHolder surfaceHolder = holder; } private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) { final double ASPECT_TOLERANCE = 0.1; double targetRatio = (double) w / h; if (sizes == null) return null; Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = h; // Try to find an size match aspect ratio and size for (Size size : sizes) { double ratio = (double) size.width / size.height; if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } // Cannot find the one match the aspect ratio, ignore the requirement if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Size size : sizes) { if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } } return optimalSize; } /* (non-Javadoc) * @see android.view.SurfaceHolder.Callback#surfaceCreated(android.view.SurfaceHolder) */ @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub surfaceHolder = holder; try { if(isCameraBack){ camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);//打开摄像头 }else{ camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);//打开摄像头 } //设置camera预览的角度,因为默认图片是倾斜90度的 camera.setDisplayOrientation(90); Size pictureSize=null; Size previewSize=null; Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewFrameRate(5); //设置旋转代码 parameters.setRotation(90); // parameters.setPictureFormat(PixelFormat.JPEG); List<Size> supportedPictureSizes = SupportedSizesReflect.getSupportedPictureSizes(parameters); List<Size> supportedPreviewSizes = SupportedSizesReflect.getSupportedPreviewSizes(parameters); if ( supportedPictureSizes != null && supportedPreviewSizes != null && supportedPictureSizes.size() > 0 && supportedPreviewSizes.size() > 0) { //2.x pictureSize = supportedPictureSizes.get(0); int maxSize = 1280; if(maxSize > 0){ for(Size size : supportedPictureSizes){ if(maxSize >= Math.max(size.width,size.height)){ pictureSize = size; break; } } } WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); DisplayMetrics displayMetrics = new DisplayMetrics(); display.getMetrics(displayMetrics); previewSize = getOptimalPreviewSize( supportedPreviewSizes, display.getWidth(), display.getHeight()); parameters.setPictureSize(pictureSize.width, pictureSize.height); parameters.setPreviewSize(previewSize.width, previewSize.height); } camera.setParameters(parameters); camera.setPreviewDisplay(holder); camera.startPreview(); } catch (Exception e) { e.printStackTrace(); } } /* (non-Javadoc) * @see android.view.SurfaceHolder.Callback#surfaceDestroyed(android.view.SurfaceHolder) */ @Override public void surfaceDestroyed(SurfaceHolder arg0) { // TODO Auto-generated method stub if(camera!=null){ camera.release(); } surfaceview = null; surfaceHolder = null; if (surfaceHolder != null) { surfaceHolder=null; } if (mediarecorder != null) { mediarecorder=null; } if (mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; } } /* (non-Javadoc) * @see android.media.MediaPlayer.OnCompletionListener#onCompletion(android.media.MediaPlayer) */ @Override public void onCompletion(MediaPlayer arg0) { // TODO Auto-generated method stub LogsUtil.i(TAG, "onCompletion"); if (mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; } recordPlayIv.setVisibility(View.VISIBLE); } /* (non-Javadoc) * @see android.media.MediaPlayer.OnPreparedListener#onPrepared(android.media.MediaPlayer) */ @Override public void onPrepared(MediaPlayer arg0) { // TODO Auto-generated method stub mVideoWidth = mediaPlayer.getVideoWidth(); mVideoHeight = mediaPlayer.getVideoHeight(); if (mVideoWidth != 0 && mVideoHeight != 0) { /* 设置视频的宽度和高度 */ surfaceHolder.setFixedSize(mVideoWidth,mVideoHeight); /* 开始播放 */ mediaPlayer.start(); } } /* (non-Javadoc) * @see android.media.MediaPlayer.OnBufferingUpdateListener#onBufferingUpdate(android.media.MediaPlayer, int) */ @Override public void onBufferingUpdate(MediaPlayer player, int arg1) { // TODO Auto-generated method stub } }
然后给出布局文件代码
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:orientation="vertical" android:layout_width="fill_parent" android:background="@drawable/login_bj" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <include android:id="@+id/Title" android:layout_alignParentTop="true" android:layout_width="fill_parent" android:layout_height="wrap_content" layout="@layout/layout_common_title"/> <LinearLayout android:layout_below="@+id/Title" android:layout_above="@+id/recordBtn" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="30dp" > <SurfaceView android:id="@+id/surfaceview" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout> <RelativeLayout android:id="@+id/videoPlay" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" > <ImageView android:src="@drawable/btn_video_play_bg" android:id="@+id/recordPlayIv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="true" android:onClick="playVideo" android:visibility="gone" /> </RelativeLayout> <RelativeLayout android:id="@+id/recordBtn" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_alignParentBottom="true"> <ImageView android:src="@drawable/video_recorder_start_btn_nor" android:id="@+id/recordIv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="true" android:onClick="recordVideo" /> </RelativeLayout> </RelativeLayout>
这里还有一些地方需要完善,在录制完成后切换会出现问题。由于时间关系这边还没去处理,在后续会进行处理,
此代码采用的sdk是17,由于在android 2.2上录制视频是横着,所以采用了高点的sdk
源码demo下载地址:http://pan.baidu.com/s/1jGmk5WM
Android切换前后置摄像头并录制视频的更多相关文章
- Android 开发 MediaRecorder使用Camera1配合录制视频
前言 MediaRecorder可以不依靠Camera API 实现视频的录制,但是如果需要切换摄像头/设置对焦/选择分辨率等等就需要Camera来参与配合录制视频.这篇博客将介绍使用Camera1来 ...
- 【Android】 Android实现录音、播音、录制视频功能
智能手机操作系统IOS与Android平分天下(PS:WP与其他的直接无视了),而Android的免费招来了一大堆厂商分分向Android示好,故Android可能会有“较好”的前景. Android ...
- 【Android Developers Training】 49. 轻松录制视频
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- Android自定义view之仿微信录制视频按钮
本文章只写了个类似微信的录制视频的按钮,效果图如下: 一.主要的功能: 1.长按显示进度条,单击事件,录制完成回调 2.最大时间和最小时间控制 3.进度条宽度,颜色设置 二.实 ...
- WebRTC网页打开摄像头并录制视频
前面我们能打开本地摄像头,并且在网页上看到摄像头的预览图像. 本文我们使用MediaRecorder来录制视频.在网页上播放录制好的视频,并能提供下载功能. html 首先创建一个html界面,放上一 ...
- Android开发 MediaRecorder使用Camera2配合录制视频(暂时有异常抛出,无法使用)
前言 这个博客本来是用来详细介绍MediaRecorder与Camera2,但是出乎预料之外,在获取mMediaRecorder.getSurface();的时候无论如何都是报错的,报错为Surfac ...
- Android使用的开发MediaRecorder录制视频
MediaRecorder除了使用录制音频.还可用于录制视频.关于MediaRecorder的具体解释大家能够參考<Android开发之MediaRecorder类具体解释>.使用Medi ...
- android实现前置后置摄像头相互切换
首先自定义一个继承自SurfaceView并且实现了SurfaceHolder.Callback接口的组件: public class CameraView extends SurfaceView i ...
- 使用Android编写录制视频小程序演示样例
主要实现录制功能的类:Camera类和MediaRecorder类.功能描写叙述:首先进入视频录制界面,点击录像button进入录像功能界面,点击录制開始录制视频, 点击停止button,将录制的视频 ...
随机推荐
- activiti实战系列 并行网关(parallelGateWay)
流程图 13.2:部署流程定义+启动流程实例 13.3:查询我的个人任务 13.4:完成我的个人任务 说明: 1) 一个流程中流程实例只有1个,执行对象有多个 2) 并行网关的功能是基于进入和外出的 ...
- android ndk之hello world
前言:Android NDK r7及以上的版本已经集成了Cygwin编译环境,也就是说,我们完全可以抛弃庞大的Cygwin了. r6及以下版本,也可以抛弃几个G的完整版,使用精简过的Mini-Cygw ...
- [struts2学习笔记] 第二节 使用Maven搞定管理和构造Struts 2 Web应用程序的七个步骤
本文地址:http://blog.csdn.net/sushengmiyan/article/details/40303897 官方文档:http://struts.apache.org/releas ...
- [shiro学习笔记]第一节 使用eclipse/myeclipse搭建一个shiro程序
本文地址:http://blog.csdn.net/sushengmiyan/article/details/39519509 shiro官网:http://shiro.apache.org/ shi ...
- EBS总账模块与其他模块数据关联关系
表名:GL_IMPORT_REFERENCES 说明:总账导入附加信息表 用途:用来追溯从子模块传入总账模块的明细,对于报表开发很有帮助 SQL 语句: select * from gl_je_hea ...
- Tomcat内核之ASCII解码的表驱动模式
我们知道Tomcat通信是建立在Socket的基础上,而套接字在服务器端和客户端传递的报文都是未经过编码的字节流,每8位组成1个字节,计算机以二进制为基础,这是由于使用晶体管的开合状态表示1和0,这样 ...
- INV 调试: 如何获取库存物料事务处理调试信息
1. 按如下方式设置系统配置文件值: 系统配置文件值 地点/用户/应用/职责层配置文件值 --汇总 FND: 启用调试日志 是 FND:调试日志层级 陈述 INV: 调试跟踪: 是 IN ...
- JQuery实战--可以编辑的表格
廊坊下雪了,15年的第二场雪,比14的来的稍晚一些,停靠在11教门前的自行车,成了廊坊师范学院最美丽的风景线.还记得以前学习css的时候,就曾经接触过如何编写设计一些表格和表单的样式,例如如何设计表格 ...
- 后端分布式系列:分布式存储-HDFS Client 设计实现解析
前面对 HDFS NameNode 和 DataNode 的架构设计实现要点做了介绍,本文对 HDFS 最后一个主要构成组件 Client 做进一步解析. 流式读取 HDFS Client 为客户端应 ...
- Docker教程:镜像构建和自动镜像构建dockerfile
http://blog.csdn.net/pipisorry/article/details/50805379 Docker透过Dockerfile来记录建立Container映象文件的每一个步骤,可 ...