欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-03-04 09:50:23
本文为用 mediarecorder 录制小视频的控件,可以设置视频录制的时间、空间大小、初始时是否打开摄像头等。 此控件为组合控件,继承自 linearlayout ,为...

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

小视频录制界面

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

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>

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