首页 > 代码库 > Android切换前后置摄像头并录制视频

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

代码:这里

Android切换前后置摄像头并录制视频