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,将录制的视频 ...
随机推荐
- Android 的 Sqlite基本操作
在 SQL 数据库中保存数据 使用数据库 将数据保存到数据库对于重复或结构化数据(比如契约信息)而言是理想之选. 本课程假定您基本熟悉 SQL 数据库并且可帮助您开始在 Android 中使用 SQL ...
- 2.Cocos2dx 3.2中的重力系统Box2D
1 添加Box2D相关的库 步骤1:右击项目所在的解决方案à添加->现有项目àE:\Installed\cocos2d-x-3.2\cocos2d-x-3.2\external\Box2D ...
- 视频编码器评测系统:VideoCodecRank
视频编码器领域一直有个比较复杂的问题:mpeg2.divx.xvid.mpeg4.vp8.vp9.x264.openh264.x265等等这一系列编码器到底哪个好?而对于同一种视频编码器,又包括了各种 ...
- 20 ViewPager Demo3指示器
MainActivity.java package com.qf.day20_viewpager_demo3; import java.util.ArrayList; import java.util ...
- 安卓程序员要拿到5000和1w的薪资,分别需要掌握哪些技术?
这个是我在逛知乎的时候发现的一个帖子,在这里小小的整理了一下,收集了一些评论,然后我分享出来,希望对自己还有同行有所帮助. 著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 链接 ...
- 指令汇C电子市场开发(一) ActionBar的使用
前话: 在学习开发谷歌电子市场的的时候,我换了一款比较高大上的模拟器--genymotion,首先去genymotion的官网注册下载,然后安装.感觉这款模拟器运行挺快的,哈哈,而且可以直接把应用拖进 ...
- React Native开发工具Nuclide使用
之前写RN的时候首选webstorm,这是之前做前端已经习惯的工具,其实RN开发官网推荐的是Nuclide工具, Nuclide是Fackbook专门为React开发IDE,今天也来尝试下,如果对we ...
- FFmpeg源代码简单分析:libavdevice的avdevice_register_all()
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- 最简单的基于Flash的流媒体示例:RTMP推送和接收(ActionScript)
===================================================== Flash流媒体文章列表: 最简单的基于Flash的流媒体示例:RTMP推送和接收(Acti ...
- hadoop cdh5的pig隐式转化(int到betyarray)不行了
cdh3上,pig支持int到chararray的隐式转化,但到cdh5不行. pig code is as follows: %default Cleaned_Log /user/usergroup ...