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


  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cuiran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值