java制作仿微信录制小视频控件

本文为用 MediaRecorder 录制小视频的控件,可以设置视频录制的时间、空间大小、初始时是否打开摄像头等。 此控件为组合控件,继承自 LinearLayout ,为防止出错,需实现 android.media.MediaRecorder.OnErrorListener 接口。

小视频录制界面

MovieRecorderView.java

import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.content.res.TypedArray;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.media.MediaRecorder;
import android.media.MediaRecorder.AudioEncoder;
import android.media.MediaRecorder.AudioSource;
import android.media.MediaRecorder.OnErrorListener;
import android.media.MediaRecorder.OutputFormat;
import android.media.MediaRecorder.VideoEncoder;
import android.media.MediaRecorder.VideoSource;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;

import com.contron.dgyj.R;
import com.contron.dgyj.common.Globals;
import com.contron.dgyj.im.ImGlobal;
import com.lidroid.xutils.util.LogUtils;

/**
 * 视频播放控件
 *
 * @author liuyinjun
 *
 * @date 2015-2-5
 */
public class MovieRecorderView extends LinearLayout implements OnErrorListener {

  private SurfaceView mSurfaceView;
  private SurfaceHolder mSurfaceHolder;
  private ProgressBar mProgressBar;

  private MediaRecorder mMediaRecorder;
  private Camera mCamera;
  private Timer mTimer;// 计时器
  private OnRecordFinishListener mOnRecordFinishListener;// 录制完成回调接口

  private int mWidth;// 视频分辨率宽度
  private int mHeight;// 视频分辨率高度
  private boolean isOpenCamera;// 是否一开始就打开摄像头
  private int mRecordMaxTime;// 一次拍摄最长时间
  private int mTimeCount;// 时间计数
  private File mVecordFile = null;// 文件

  public MovieRecorderView(Context context) {
    this(context, null);
  }

  public MovieRecorderView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public MovieRecorderView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MovieRecorderView, defStyle, 0);
    mWidth = a.getInteger(R.styleable.MovieRecorderView_width, 320);// 默认320
    mHeight = a.getInteger(R.styleable.MovieRecorderView_height, 240);// 默认240

    isOpenCamera = a.getBoolean(R.styleable.MovieRecorderView_is_open_camera, true);// 默认打开
    mRecordMaxTime = a.getInteger(R.styleable.MovieRecorderView_record_max_time, 10);// 默认为10

    LayoutInflater.from(context).inflate(R.layout.movie_recorder_view, this);
    mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview);
    mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
    mProgressBar.setMax(mRecordMaxTime);// 设置进度条最大量

    mSurfaceHolder = mSurfaceView.getHolder();
    mSurfaceHolder.addCallback(new CustomCallBack());
    mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    a.recycle();
  }

  /**
   *
   * @author liuyinjun
   *
   * @date 2015-2-5
   */
  private class CustomCallBack implements Callback {

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
      if (!isOpenCamera)
        return;
      try {
        initCamera();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
      if (!isOpenCamera)
        return;
      freeCameraResource();
    }

  }

  /**
   * 初始化摄像头
   *
   * @author liuyinjun
   * @date 2015-2-5
   * @throws IOException
   */
  private void initCamera() throws IOException {
    if (mCamera != null) {
      freeCameraResource();
    }
    try {
      mCamera = Camera.open();
    } catch (Exception e) {
      e.printStackTrace();
      freeCameraResource();
    }
    if (mCamera == null)
      return;

    setCameraParams();
    mCamera.setDisplayOrientation(90);
    mCamera.setPreviewDisplay(mSurfaceHolder);
    mCamera.startPreview();
    mCamera.unlock();
  }

  /**
   * 设置摄像头为竖屏
   *
   * @author liuyinjun
   * @date 2015-2-5
   */
  private void setCameraParams() {
    if (mCamera != null) {
      Parameters params = mCamera.getParameters();
      params.set("orientation", "portrait");
      mCamera.setParameters(params);
    }
  }

  /**
   * 释放摄像头资源
   *
   * @author liuyinjun
   * @date 2015-2-5
   */
  private void freeCameraResource() {
    if (mCamera != null) {
      mCamera.setPreviewCallback(null);
      mCamera.stopPreview();
      mCamera.lock();
      mCamera.release();
      mCamera = null;
    }
  }

  private void createRecordDir() {
    File sampleDir = new File(Environment.getExternalStorageDirectory() + File.separator + "im/video/");
    if (!sampleDir.exists()) {
      sampleDir.mkdirs();
    }
    File vecordDir = sampleDir;
    // 创建文件
    try {
      mVecordFile = File.createTempFile("recording", ".mp4", vecordDir);//mp4格式
      LogUtils.i(mVecordFile.getAbsolutePath());
    } catch (IOException e) {
    }
  }

  /**
   * 初始化
   *
   * @author liuyinjun
   * @date 2015-2-5
   * @throws IOException
   */
  private void initRecord() throws IOException {
    mMediaRecorder = new MediaRecorder();
    mMediaRecorder.reset();
    if (mCamera != null)
      mMediaRecorder.setCamera(mCamera);
    mMediaRecorder.setOnErrorListener(this);
    mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
    mMediaRecorder.setVideoSource(VideoSource.CAMERA);// 视频源
    mMediaRecorder.setAudioSource(AudioSource.MIC);// 音频源
    mMediaRecorder.setOutputFormat(OutputFormat.MPEG_4);// 视频输出格式
    mMediaRecorder.setAudioEncoder(AudioEncoder.AMR_NB);// 音频格式
    mMediaRecorder.setVideoSize(mWidth, mHeight);// 设置分辨率:
    // mMediaRecorder.setVideoFrameRate(16);// 这个我把它去掉了,感觉没什么用
    mMediaRecorder.setVideoEncodingBitRate(1 * 1024 * 512);// 设置帧频率,然后就清晰了
    mMediaRecorder.setOrientationHint(90);// 输出旋转90度,保持竖屏录制
    mMediaRecorder.setVideoEncoder(VideoEncoder.MPEG_4_SP);// 视频录制格式
    // mediaRecorder.setMaxDuration(Constant.MAXVEDIOTIME * 1000);
    mMediaRecorder.setOutputFile(mVecordFile.getAbsolutePath());
    mMediaRecorder.prepare();
    try {
      mMediaRecorder.start();
    } catch (IllegalStateException e) {
      e.printStackTrace();
    } catch (RuntimeException e) {
      e.printStackTrace();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 开始录制视频
   *
   * @author liuyinjun
   * @date 2015-2-5
   * @param fileName
   *      视频储存位置
   * @param onRecordFinishListener
   *      达到指定时间之后回调接口
   */
  public void record(final OnRecordFinishListener onRecordFinishListener) {
    this.mOnRecordFinishListener = onRecordFinishListener;
    createRecordDir();
    try {
      if (!isOpenCamera)// 如果未打开摄像头,则打开
        initCamera();
      initRecord();
      mTimeCount = 0;// 时间计数器重新赋值
      mTimer = new Timer();
      mTimer.schedule(new TimerTask() {

        @Override
        public void run() {
          // TODO Auto-generated method stub
          mTimeCount++;
          mProgressBar.setProgress(mTimeCount);// 设置进度条
          if (mTimeCount == mRecordMaxTime) {// 达到指定时间,停止拍摄
            stop();
            if (mOnRecordFinishListener != null)
              mOnRecordFinishListener.onRecordFinish();
          }
        }
      }, 0, 1000);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  /**
   * 停止拍摄
   *
   * @author liuyinjun
   * @date 2015-2-5
   */
  public void stop() {
    stopRecord();
    releaseRecord();
    freeCameraResource();
  }

  /**
   * 停止录制
   *
   * @author liuyinjun
   * @date 2015-2-5
   */
  public void stopRecord() {
    mProgressBar.setProgress(0);
    if (mTimer != null)
      mTimer.cancel();
    if (mMediaRecorder != null) {
      // 设置后不会崩
      mMediaRecorder.setOnErrorListener(null);
      mMediaRecorder.setPreviewDisplay(null);
      try {
        mMediaRecorder.stop();
      } catch (IllegalStateException e) {
        e.printStackTrace();
      } catch (RuntimeException e) {
        e.printStackTrace();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  /**
   * 释放资源
   *
   * @author liuyinjun
   * @date 2015-2-5
   */
  private void releaseRecord() {
    if (mMediaRecorder != null) {
      mMediaRecorder.setOnErrorListener(null);
      try {
        mMediaRecorder.release();
      } catch (IllegalStateException e) {
        e.printStackTrace();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    mMediaRecorder = null;
  }

  public int getTimeCount() {
    return mTimeCount;
  }

  /**
   * @return the mVecordFile
   */
  public File getmVecordFile() {
    return mVecordFile;
  }

  /**
   * 录制完成回调接口
   *
   * @author liuyinjun
   *
   * @date 2015-2-5
   */
  public interface OnRecordFinishListener {
    public void onRecordFinish();
  }

  @Override
  public void onError(MediaRecorder mr, int what, int extra) {
    try {
      if (mr != null)
        mr.reset();
    } catch (IllegalStateException e) {
      e.printStackTrace();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

movie_recorder_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@android:color/background_dark"
  android:orientation="vertical">

  <SurfaceView
     android:id="@+id/surfaceview"
     android:layout_width="fill_parent"
     android:layout_height="0dp"
     android:layout_weight="1"
     />

  <ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="2dp"
    />

</LinearLayout>

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@android:color/background_dark"
  android:orientation="vertical">

  <SurfaceView
     android:id="@+id/surfaceview"
     android:layout_width="fill_parent"
     android:layout_height="0dp"
     android:layout_weight="1"
     />

  <ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="2dp"
    />

</LinearLayout>

以上所述就是本文的全部内容了,希望大家能够喜欢。

(0)

相关推荐

  • java获取优酷视频地址示例

    复制代码 代码如下: import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.URL;import java.util.regex.Matcher;import java.util.regex.Pattern; import net.sf.json.JSONArray;import net.sf.json.JSONException;import net.sf.json.JSONObject;

  • java解析sina视频

    用一个例子来说明,比如这个http://video.sina.com.cn/v/b/75314002-1648211320.html.用火狐打开,开启firebug,得到如下信息. 其中在这个请求 http://v.iask.com/v_play.php?vid=75314002&uid=1648211320&pid=478&tid=&plid=4001&prid=ja_7_3485822616&referrer=&ran=0.29368022363

  • Java程序中添加播放MIDI音乐功能的实现方法详解

    JAVA 在多媒体处理方面的确优势不大,但是我们在程序中有些时候又需要一些音乐,如果播放的音乐是wav等波形音频文件,又很大的话,所以背景音乐最好就是MIDI了,可是网上很多播放MIDI的教程都是简单的几句话的例子.没有考虑资源的释放问题,如果程序长久运行的话,就会出现内存越耗越多的情况,最后会抛出一个 java.lang.OutOfMemoryError..在MIDI的播放中,一个类是比较重要的,那就是 MidiSystem 类,负责整个MIDI播放设备等的管理,其实就是 Seqencer,它

  • jsp播放视频文件的方法总结

    本文实例讲述了jsp播放视频文件的方法.分享给大家供大家参考,具体如下: 1.avi格式 代码片断如下: JSP代码: <object id="video" width="400" height="200" border="0" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA"> <param name="ShowDispl

  • java音频播放示例分享(java如何播放音频)

    这是一份精简后的代码,能够支持的格式十分有限. 复制代码 代码如下: package com.hongyuan.test; import java.io.File;import java.io.IOException; import javax.sound.sampled.AudioFormat;import javax.sound.sampled.AudioInputStream;import javax.sound.sampled.AudioSystem;import javax.sound

  • (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    这个其实很简单,只要在HTML上添加以上代码就OK了,前提是你的电脑上已经安装了播放器,如RealPlay. 复制代码 代码如下: <embed src="C:/mp3/10.19/画心.mp3" width="480" height="100"02. loop="false" autostart="false"> </embed> 还有更多的的播放器和设置可供选择: 页面插入REA

  • 实例解析使用Java实现基本的音频播放器的编写要点

    Java音频播放,因为必须依赖到本地环境,所以JAVA在音频处理方面优势不大,或者说打从Java体系开发时就没太多的考虑音频播放因素,要知道最早的Java 1.1版本中,没有后来的javax.sound包,音频只能通过Applet包调取-- 遗憾的是,在图形程序开发中,我们的程序却又难免要使用到背景音乐.效果音等配合图像操作,哎,这实在是Sun大神给我们开的一个不打不小的玩笑.万幸后来Sun大神开眼,提供了javax.sound包,才解救我们于水深火热当中~ 但是继之而来的问题是,在javax.

  • java实现优酷视频地址解析示例代码分享

    举个例子比较好理解,比如我现在要下http://v.youku.com/v_show/id_XNDM2Mjc0MzAw.html这个视频.这里我们要获得的是视频的id,就是XNDM2Mjc0MzAw这部分,这是一个视频唯一的,所以在解析的时候肯定会用到. 为了能看清楚youku视频的播放过程,可以使用火狐的插件firebug对网页进行跟踪,如下图. 可以看到有很多GET,我们要找的应该是以这个id作为参数的GET,在下面我们可以找到这个链接http://v.youku.com/player/ge

  • java播放声音类和一个简单示例

    播放声音的类 复制代码 代码如下: import java.io.File;import java.io.IOException; import javax.sound.sampled.AudioFormat;import javax.sound.sampled.AudioInputStream;import javax.sound.sampled.AudioSystem;import javax.sound.sampled.DataLine;import javax.sound.sampled

  • java制作仿微信视频播放控件

    此控件继承自 SurfaceView,利用 MediaPlayer 播放视频. 小视频播放界面 MoviePlayerView.java import java.io.IOException; import android.content.Context; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListene

随机推荐