java制作仿微信录制小视频控件
程序员文章站
2024-03-04 09:50:23
本文为用 mediarecorder 录制小视频的控件,可以设置视频录制的时间、空间大小、初始时是否打开摄像头等。 此控件为组合控件,继承自 linearlayout ,为...
本文为用 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>
以上所述就是本文的全部内容了,希望大家能够喜欢。
上一篇: Android编程实现大图滚动显示的方法