Android切換前後置攝像頭並錄製視訊
【原文:http://blog.csdn.net/cuiran/article/details/12779005】
專案需要對微信的視訊模組也看了一下,在此就對這塊進行了一個開發。首先給出效果圖
首先給出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
相關文章
- iphone 4 攝像頭是前後切換iPhone
- WebRTC網頁開啟攝像頭並錄製視訊Web網頁
- px30-android8.1-USB攝像頭錄製視訊異常Android
- android短視訊錄製與頭像跟隨(一)Android
- Android 呼叫攝像頭功能【拍照與視訊】Android
- Android呼叫攝像頭拍照並顯示照片Android
- Android呼叫攝像頭Android
- 【Android】【opencv】實現攝像頭拍照和錄影AndroidOpenCV
- android opencv 前置攝像頭AndroidOpenCV
- Android呼叫攝像頭拍照Android
- android 開啟攝像頭Android
- 修正Android攝像頭APIAndroidAPI
- Android 呼叫攝像頭拍照Android
- Android如何呼叫攝像頭Android
- 3、Opencv播放視訊、儲存、暫停視訊,開啟攝像頭OpenCV
- 純JavaScript實現的呼叫裝置攝像頭並拍照的功能JavaScript
- 在Android中呼叫攝像頭拍照並顯示出來Android
- Android提供的攝像頭拍照Android
- iOS 儲存攝像頭H264視訊流iOS
- 電腦釘釘攝像頭許可權在哪設定 電腦釘釘視訊會議攝像頭黑屏
- MiniVCap 用普通usb攝像頭做視訊錄影軟體!可長期持續錄影
- [譯]Android的多攝像頭支援Android
- [譯] Android 的多攝像頭支援Android
- 華為P9拆機圖解評測 雙後置攝像頭圖解
- opencv python 從攝像頭獲取視訊/從檔案獲取視訊 /儲存視訊OpenCVPython
- android studio之簡單呼叫攝像頭並且獲取其照片Android
- AndroidCamera2拍照(三)——切換攝像頭,延時拍攝和閃光模式Android模式
- Android 攝像頭預覽懸浮窗Android
- 照片系列之android呼叫攝像頭拍照Android
- Android開發之呼叫攝像頭拍照Android
- 攝像頭背後的應用–資訊圖
- Android視訊錄製命令screenrecordAndroid
- 攝像頭操作指南
- Android音視訊之MediaRecorder音視訊錄製Android
- [Android]Android視訊錄製命令screenrecordAndroid
- ToDesk勾上攝像頭會看到我嗎?如何關閉攝像頭
- golang 有哪些庫可以做攝像頭/視訊人臉識別的?Golang
- 谷歌揭秘Pixel 4設計:確認雙後置攝像頭,全玻璃背殼谷歌