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,将录制的视频 ...
随机推荐
- tomcat生命周期的管理——生命周期统一接口Lifecycle
我们知道Tomcat的架构设计是清晰的.模块化的,其拥有很多组件,假如我们要启动Tomcat,可以一个一个启动组件,但这样启动有很多缺点,不仅麻烦,而且容易漏了组件启动,还会对后面动态组件扩展带来麻烦 ...
- Erlang简单并行服务器
Erlang简单并行服务器(金庆的专栏)Erlang并行服务器为每个Tcp连接创建对应的连接进程,处理客户端数据.参考 Erlang程序设计(第2版)17.1.3 顺序和并行服务器并行服务器的诀窍是: ...
- sybase isql命令参数详解
isql 实用工具使您得以输入 Transact-SQL 语句.系统过程和脚本文件. 语法 isql [-?] | [-L] | [ { {-U login_id [-P password]} | - ...
- 基于OpenCV 的美颜相机推送直播流
程序流程: 1.图像采集 先从opencv(2.4.10版本)采集回来摄像头的图像,是一帧一帧的 每一帧图像是一个矩阵,opencv中的mat 数据结构. 2.人脸的美化 人脸美化,我们用的皮肤检测, ...
- 关闭Win10自动更新
使用过Windows10系统的小伙伴们都清楚,在Windows10中强制开启了自动更新功能,我们无法通过常规的办法关闭自动更新功能,那么我们该怎么去关闭自动更新呢?欢迎速来围观我的经验啦. 工具/原料 ...
- Win 10 下 android studio显示 Intel haxm无法安装,以及VT-X和hyper-x的冲突问题
我 的电脑是神舟战神k650c i7 D4,处理器是Intel core i7 4710-MQ,系统是win 10的 我心血来潮想学习一下安卓开发,就首先安装了android s ...
- XMLTABLE
XMLTABLE Syntax Description of the illustration xmltable.gif XMLnamespaces_clause::= Description ...
- Android进阶(十三)网络爬虫&json应用
刚开始接触网络爬虫,怎一个"菜"字了得!经过几次的折磨,对其原理以及其中用到的json技术有了大致的了解,故作一总结,供有同样迷惑的朋友参考学习. 自己爬取的网站内容为12306的 ...
- Android官方命令深入分析之dmtracedump
dmtracedump是一个根据log文件生成图形化调用堆栈的工具(除了Traceview之外). dmtracedump的用法: dmtracedump [-ho] [-s sortable] [- ...
- (七十一)关于UITableView退出崩溃的问题和滚动到底部的方法
[TableView退出崩溃的问题] 最近在使用TableView时偶然发现在TableView中数据较多时,如果在滚动过程中退出TableView到上一界面,会引起程序的崩溃,经过网上查阅和思考我发 ...