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,将录制的视频 ...
随机推荐
- 19 主线程向子线程发送信息(handler)
package com.fmy.handler; import android.app.Activity; import android.os.Bundle; import android.os.Ha ...
- 4.2、Android Studio压缩你的代码和资源
为了让你的APK文件尽可能的小,你需要在构建的时候开启压缩来移除无用的代码和资源. 代码压缩可在ProGuard中使用,可以检测和清除无用的类,变量,方法和属性,甚至包括你引用的库.ProGuard同 ...
- Servlet之异常处理
当一个 Servlet 抛出一个异常时,Web 容器在使用了exception-type 元素的 web.xml 中搜索与抛出异常类型相匹配的配置. 前提是必须在 web.xml 中使用 error- ...
- SDL2源代码分析1:初始化(SDL_Init())
===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...
- Android:android sdk源码中怎么没有httpclient的源码了
欢迎关注公众号,每天推送Android技术文章,二维码如下:(可扫描) 今天想使用这个API,怎么也找不到.废了好多时间... 查阅资料才知道如下解释: 在android 6.0(API 23)中,G ...
- 【嵌入式开发】 嵌入式开发工具简介 (裸板调试示例 | 交叉工具链 | Makefile | 链接器脚本 | eclipse JLink 调试环境)
作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42239705 参考博客 : [嵌入式开发]嵌入式 开发环境 (远 ...
- 【Android 应用开发】 Android APK 反编译 混淆 反编译后重编译
反编译工具 : 总结了一下 linux, windows, mac 上的版本, 一起放到 CSDN 上下载; -- CSDN 下载地址 : http://download.csdn.net/detai ...
- Android学习之AppWidget高级效果
接着AppWidget基础学习,今天是一个"进阶版"的小例子,用来检验一下自己的学习效果.于是就做了一个掷骰子的Widget. 方便大家观看,先截图如下: 需要注意的是在drawa ...
- (七十一)关于UITableView退出崩溃的问题和滚动到底部的方法
[TableView退出崩溃的问题] 最近在使用TableView时偶然发现在TableView中数据较多时,如果在滚动过程中退出TableView到上一界面,会引起程序的崩溃,经过网上查阅和思考我发 ...
- OpenCV Python教程(1、图像的载入、显示和保存)
原文地址:http://blog.csdn.net/sunny2038/article/details/9057415 转载请详细注明原作者及出处,谢谢! 本文是OpenCV 2 Computer ...