使用Android编写录制视频小程序示例

主要实现录制功能的类:Camera类和MediaRecorder类。功能描述:首先进入视频录制界面,点击录像按钮进入录像功能界面,点击录制开始录制视频, 点击停止按钮,将录制的视频存放到指定目录下存放。下面通过Samples_10_3程序实现具体功能:

(1)新建一个Android Application Project项目取名为Samples_10_3

(2)在res/layout文件修改activity_main.xml主布局文件(主要添加一个标题和摄像按钮)

<?xml version="1.0" ?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:orientation="vertical">

	<TextView
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:text="@string/hello"/>

	<Button
		android:id="@+id/camera_button"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_gravity="center_horizontal"
		android:text="<span style="color:#ff0000;">摄像</span>"/>
</LinearLayout>

(3)因为要实现摄像的功能,在res/layout目录下添加video.xml布局文件(主要包括SurfaceView视图控件、摄像按钮和停止摄像按钮)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/linearLayout1" >
    <SurfaceView
    	android:id="@+id/surface_view"
    	android:layout_width="wrap_content"
    	android:layout_height="fill_parent"
    	android:layout_weight="0.58"/>
	<LinearLayout
		android:id="@+id/linearLayout2"
		android:layout_width="wrap_content"
		android:layout_height="match_parent"
		android:orientation="vertical">

		<Button
			android:id="@+id/start"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="<span style="color:#ff0000;">录制</span>"/>
		<Button
			android:id="@+id/stop"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="<span style="color:#ff0000;">停止</span>"/>
	</LinearLayout>
</LinearLayout>

(4)首先需要给程序必要的权限才能读/写、访问Camera、录制音频文件、创建删除文件等权限。在程序的AndroidManifest.xml程序清单文件下添加如下权限:

读取Camera权限

<span style="color:#ff0000;"><uses-permission android:name="android.permission.CAMERA" ></uses-permission> </span> 
<span style="color:#cc66cc;">视频录制权限</span>
<span style="color:#ff0000;"><uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission></span>
<span style="color:#cc66cc;">读写内存卡权限</span>
<span style="color:#ff0000;"><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission></span>
<span style="color:#cc66cc;">创建和删除文件目录权限</span>
<span style="color:#ff0000;"> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /></span>

因为因为VideoRecord.java类是另一个Activity所以还需要在AndroidMainifest.xml文件中添加这样一段代码(一般这里的类名需要写完整的类结构):

<span style="color:#ff0000;"><activity android:name=".VideoRecord"></activity></span>

(5)下面就是两个Activity实现布局文件调用和具体功能的实现:MainActivity.java类(摄像主界面)和VideoRecord类(摄像功能):

A.MainActivity.java类的具体实现:

package com.example.samples_10_3;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.content.Intent;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button=(Button)this.findViewById(R.id.camera_button);	//实例化摄像按钮对象
        button.setOnClickListener(new View.OnClickListener() {
			//为摄像按钮添加事件监听
			@Override
			public void onClick(View arg0) {
				<span style="color:#33cc00;">Intent intent=new Intent();
				intent.setClass(MainActivity.this, VideoRecord.class);		//intent对象指定的类
				MainActivity.this.startActivity(intent);	//启动新的Activity</span>
			}
		});
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

B.VideoRecord类的具体实现:

package com.example.samples_10_3;

import android.app.Activity;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.widget.Button;
import android.media.MediaRecorder;
import android.hardware.Camera;
import java.io.File;
import android.os.Bundle;
import android.graphics.PixelFormat;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.content.pm.ActivityInfo;
import android.os.Environment;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.media.MediaRecorder.OnErrorListener;
import java.io.IOException;
import android.view.KeyEvent;
import android.content.Intent;

public class VideoRecord extends Activity implements Callback  {
	private SurfaceView surfaceView=null;		//创建一个空的SurfaceView对象
	private SurfaceHolder surfaceHolder=null;	//创建一个空的SurfaceHolder对象
	private Button startButton=null;		//创建一个开始录制Button组件对象
	private Button stopButton=null;			//创建一个停止录制Button组件对象
	private MediaRecorder mediaRecorder=null;		//创建一个空的MediaRecorder对象
	private Camera camera=null;			//创建一个空的Camera对象
	private boolean previewRunning=false;		//预览状态
	private File videoFile=null;		//录制视频文件的File对象
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		this.getWindow().setFormat(PixelFormat.TRANSLUCENT);	//窗口设为半透明
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);		//窗口去掉标题
		this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);	//窗口设置为全屏
		//setRequestedOrientation类翻转Preview
		this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);	//设置预览水平翻转
		this.setContentView(R.layout.video);

		surfaceView=(SurfaceView)this.findViewById(R.id.surface_view);	//实例化SurfaceView对象
		surfaceHolder=surfaceView.getHolder();	//获取SurfaceHolder对象
		surfaceHolder.addCallback(this);	//注册实现好的Callback
		surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);	//设置缓存类型
		startButton=(Button)this.findViewById(R.id.start);	//实例化开始录制按钮的Button组件对象
		stopButton=(Button)this.findViewById(R.id.stop);	//实例化停止录制按钮的Button组件对象
		startButton.setEnabled(true);
		stopButton.setEnabled(false);

		//添加摄像按钮单击监听
		startButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// 调用开始摄像方法
				startRecording();
			}
		});
		//添加停止按钮单击监听
		stopButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				//调用停止摄像方法
				stopRecording();
			}
		});
	}
	/**
	 * 开始摄像方法
	 */
	public void startRecording()
	{
		try
		{
			stopCamera();	//调用停止Camera方法
			if(!getStorageState())	//判断是否有存储卡,如果没有就关闭页面
			{
				VideoRecord.this.finish();
			}
			<span style="color:#009900;">//获取存储(sdCard)的根目录
			String sdCard=Environment.getExternalStorageDirectory().getPath();
			//设置相片存放的目录
			String dirFilePath=sdCard+File.separator+"MyVideo";
			//获取录制文件夹路径的File对象
			File dirFile=new File(dirFilePath);
			if(!dirFile.exists())	//判断文件夹是否存在
			{
				dirFile.mkdir();	//创建文件
			}</span>
			//创建录制视频临时文件
			videoFile=File.createTempFile("video", ".3gp",dirFile);
			//初始化MediaRecorder对象
			mediaRecorder=new MediaRecorder();

			mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());	//设置预览
			mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);	//Camera视频源
			mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);	//录音源为麦克风

			//输出格式为3gp格式
			mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
			mediaRecorder.setVideoSize(480, 320);		//视频尺寸
			mediaRecorder.setVideoFrameRate(15);		//视频帧的频率
			mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);		//视频编码
			mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);	//音频编码
			mediaRecorder.setMaxDuration(10000);	//最大期限
			mediaRecorder.setOutputFile(videoFile.getAbsolutePath());	//保存路径
			mediaRecorder.prepare();	//准备录制
			mediaRecorder.start();		//开始录制
			//文件录制错误监听
			mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {

				@Override
				public void onError(MediaRecorder arg0, int arg1, int arg2) {
					// 停止摄像方法
					stopRecording();
				}
			});
			startButton.setText("录制中");
			startButton.setEnabled(false);		//开始录制按钮失效
			stopButton.setEnabled(true);		//停止录制按钮生效
		}catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	/**
	 * 手机按键监听事件
	 */
	@Override
	 public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		//判断手机按键按下是否是返回键
		if(keyCode==KeyEvent.KEYCODE_BACK)
		{
			stopRecording();	//调用停止摄像方法
			Intent intent=new Intent();		//初始化Intent
			intent.setClass(VideoRecord.this, MainActivity.class);		//指定Intent对象启动的类
			intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);	//清楚该进程空间中的所有Activity
			this.startActivity(intent);		//启动新的Activity
			VideoRecord.this.finish();		//销毁这个Activity
		}
		return super.onKeyDown(keyCode, event);
	}
	/**
	 * 获取sdCard存储状态
	 * @return 手机sd卡的存储状态
	 */
	public boolean getStorageState()
	{
		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))	//判断sdCard的存储状态
		{
			return true;
		}else
		{
			<span style="color:#ff6600;">new AlertDialog.Builder(this)		//创建AlertDialog对象
			.setTitle("提示信息")		//设置信息标题
			.setMessage("未安装SD卡,请检查你的设备")	//设置信息内容
			.setPositiveButton("确定", new android.content.DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface arg0, int arg1) {
					// 结束应用程序
					VideoRecord.this.finish();
				}
			})
			.show();		//设置弹出提示框</span>
			return false;
		}
	}
	/**
	 * 停止摄像
	 */
	public void stopRecording()
	{
		if(mediaRecorder!=null)		//判定MediaRecorder对象是否为空
		{
			mediaRecorder.stop();	//停止摄像
			mediaRecorder.release();	//释放资源
			mediaRecorder=null;		//置空MediaRecorder对象

			startButton.setEnabled(true);		//摄像按钮生效
			stopButton.setEnabled(false);	//停止按钮生效

			startButton.setText("录制");
			isSave();	//调用是否保存方法
		}
		stopCamera();		//调用停止Camera方法
		prepareCamera();	//调用初始化Camera对象
		startCamera();		//调用开始Camera方法
	}
	/**
	 * 开始Camera
	 */
	public void startCamera()	//判断预览开启
	{
		if(previewRunning)
		{
			camera.stopPreview();	//停止预览
		}
		try
		{
			//设置用SurfaceView作为承载镜头取景画面显示
			camera.setPreviewDisplay(surfaceHolder);
			camera.startPreview();		//开始预览
			previewRunning=true;	//设置预览状态为true
		}catch(IOException e)
		{
			e.printStackTrace();
		}
	}
	/**
	 * 初始化Camera方法
	 */
	public void prepareCamera()
	{
		camera=Camera.open();		//初始化Camera
		try
		{
			camera.setPreviewDisplay(surfaceHolder);	//设置预览
		}catch(IOException e)
		{
			camera.release();	//释放相机资源
			camera=null;	//置空Camera对象
		}
	}
	/**
	 * 是否保存视频录制的文件
	 */
	public void isSave()
	{
		AlertDialog alertDialog=new AlertDialog.Builder(this).create();		//创建AlertDialog对象
		alertDialog.setTitle("提示信息");
		alertDialog.setMessage("是否保存"+videoFile.getName()+"视频文件?");	//设置信息内容
		//设置确认按钮,并添加按钮监听事件
		alertDialog.setButton("确认", new android.content.DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface arg0, int arg1) {
				// TODO Auto-generated method stub

			}
		});
		alertDialog.setButton("取消", new android.content.DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface arg0, int arg1) {
				//判断文件是否存在,存在删除文件
				if(videoFile.exists())
				{
					videoFile.delete();
				}

			}
		});
		alertDialog.show();		//设置弹出提示框
	}
	/**
	 * 停止Camera
	 */
	public void stopCamera()
	{
		if(camera!=null)	//判断Camera对象不为空
		{
			camera.stopPreview();	//停止预览
			camera.release();		//释放Camera资源
			camera=null;
			previewRunning=false;	//设置预览状态为false
		}
	}
	/**
	 * 初次实例化,预览界面创建时,该方法被调用
	 */
	@Override
	public void surfaceCreated(SurfaceHolder arg0)
	{
		prepareCamera();	//调用初始化Camera
	}
	/**
	 * 当预览界面的格式和大小发生变化时,该方法调用
	 */
	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
	{
		startCamera();		//调用开始Camera
	}
	/**
	 * 当预览界面关闭时,该方法被调用
	 */
	@Override
	public void surfaceDestroyed(SurfaceHolder arg0)
	{
		stopCamera();
	}

}

(6)程序运行的结果如图所示:

A.进入视频录制界面:

B.点击摄像按钮进入视频预览功能:

C.点击录制按钮后视频文件被保存在MyVideo文件夹下面:

D.MyVideo文件夹下录制好的文件:

(7)代码程序具体详解:

                       //获取存储(sdCard)的根目录
			String sdCard=Environment.getExternalStorageDirectory().getPath();
			//设置相片存放的目录
			String dirFilePath=sdCard+File.separator+"MyVideo";
			//获取录制文件夹路径的File对象
			File dirFile=new File(dirFilePath);
			if(!dirFile.exists())	//判断文件夹是否存在
			{
				dirFile.mkdir();	//创建文件
			}
			//创建录制视频临时文件
			videoFile=File.createTempFile("video", ".3gp",dirFile);

获取手机sdCard根目录,指定根目录下自定义文件夹用于存放录制视频文件,以3gp格式存储,video为前缀。

<span style="white-space:pre">		</span>//判断手机按键按下是否是返回键
		if(keyCode==KeyEvent.KEYCODE_BACK)
		{
			stopRecording();	//调用停止摄像方法
			Intent intent=new Intent();		//初始化Intent
			intent.setClass(VideoRecord.this, MainActivity.class);		//指定Intent对象启动的类
			intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);	//清楚该进程空间中的所有Activity
			this.startActivity(intent);		//启动新的Activity
			VideoRecord.this.finish();		//销毁这个Activity
		}

这是Activity类的onKeyDown事件用于监听,点击手机返回键时,回到MainActivity窗体并销毁VideoRecord这个Activity.指定Intent.FLAG_ACTIVITY_CLEAR_TOP,例如现在的栈情况为:A
B C D 。D此时通过intent跳转到B,如果这个intent添加FLAG_ACTIVITY_CLEAR_TOP标记,则栈情况变为:A B。

至此所有的摄像功能的介绍都已经结束了,录制视频需要考虑调用摄像头功能和音频录制功能。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 18:48:17

使用Android编写录制视频小程序示例的相关文章

一名Android开发者的微信小程序填坑之路(2)

前言 上一篇是九月二十七日写的,而这一篇我动笔的时间是十月十日(特殊的日子),中间相隔十三天--当然是因为国庆节.说老实话,这十三天里面我都没有碰和小程序有关的东西--毕竟学习小程序的开发也只是起于兴趣,而平时的工作并不会涉及与其相关的东西--但是在这十三天里,我能明显的感受到小程序热正在逐渐的消退,或者说大家正在逐渐以一种较为平和的姿态接受它的存在,其实这是一件好事.期待公测的到来. 接下来我就直接进入正题了,另外,文末我想和大家分享一下我的国庆节. PS:这篇文章是接着上一篇文章 一名And

手把手教你构建一个音视频小程序

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯视频云终端团队发表于云+社区专栏 腾讯云提供了全套技术文档和源码来帮助您快速构建一个音视频小程序,但是再好的源码和文档也有学习成本,为了尽快的能调试起来,我们还提供了一个免费的一键部署服务:您只需轻点几下鼠标,就可以在自己的账号下获得一个音视频小程序,同时附送一台拥有独立域名的测试服务器,让您可以在 5 分钟内快速构建出自己的测试环境. 通过微信公众平台授权登录腾讯云 打开 微信公众平台 注册并登录小程序,按如下步骤操作: 单

一名Android开发者的微信小程序填坑之路(1)

前言 首先要声明的是,我是一名 Android 开发者,之前基本没有前端开发经验,甚至连 JS ,HTML 都是为了开发小程序现学的一些皮毛--所以文章中所提到的一些点也许在资深前端开发者看来只是小case,但是站在一个 Android 开发者的角度来看确实是大坑. 前面就不说太多东西了,文章的末尾再谈谈我对小程序的一些看法--这篇文章主要是谈谈在开发小程序的过程中遇到的一些坑. PS:推荐一下我写的一个微信小程序版的Gank客户端:wechat-weapp-gank 正文 1,获取小程序开发工

开发一个微笑小程序示例

一.注册小程序账号 1.进入微信公众平台(https://mp.weixin.qq.com/),注册小程序账号,根据提示填写对应的信息即可.2.注册成功后进入首页,在 小程序发布流程->小程序开发与管理->配置服务器中,点击“开发者设置”.3.会获得一个AppID,记录AppID,后面创建项目时会用到. 注意:如果要以非管理员微信号在手机上体验该小程序,那么我们还需要操作“绑定开发者”.即在“用户身份”-“开发者”模块,绑定上需要体验该小程序的微信号.本教程默认注册帐号.体验都是使用管理员微信

Java仿短视频小程序全栈开发实战视频教程+课程代码

第1章 微信小程序初学入门第2章 微信小程序的基础组件学习第3章 form表单组件与小程序前后端通信第4章 产品介绍与数据库规划介绍第5章 开发用户登录注册与用户信息第6章 上传视频业务流程开发第7章 视频展现页开发第8章 开发视频的留言板第9章 开发短视频后台办理体系第10章 项目上线与发布 下载地址:百度网盘 原文地址:http://blog.51cto.com/13870071/2142671

微信小程序-----安装,编写第一个小程序和运行到手机端

第一步: 微信公众平台注册账号,并选择小程序,网址:mp.weixin.qq.com 填写相关信息,如:主体类型(个人或者企业) AppID  在开发中都是用的到的,服务器域名在网络请求也是用的到的. 完成信息之后,下载开发工具: 下载地址: https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html 选择自己需要的版本,下载直接安装,和平常的软件安装一样,直接运行 用微信扫码登录即可,然后点击添加项目, 输入申请的AppID

用android去写一个小程序

前言: 软工的一个小作业:实现"黄金分割小游戏", 需要结对编程,队友:陈乐云(http://www.cnblogs.com/clyln/),用时两天. 早期思路设计: 采用键值对的形式,以Map作为存储结构.优点:能够将数据与用户对应,缺点:采用java实现过于复杂,工程量过大,需要消耗大量资源,类型转换容易出错. 后期思路设计: 采用二维数组:第一行用于存储用户输入原始数据,第二行用于存储中间数据(第一行的与G值做差的绝对值),第三行用于保存用户得分. 优点:实现简单,易于运算 分

微信小程序通过api接口将json数据展现到小程序示例

实现知乎客户端的一个重要知识前提就是,要知道怎么通过知乎新闻的接口,来把数据展示到微信小程序端上. 那么我们这一就先学习一下,如何将接口获取到的数据展示到微信小程序上. 1.用到的知识点 <1> wx.request 请求接口资源(微信小程序api中的发起请求部分) <2>swiper 实现轮播图的组件 <3>wx:for 循环语句 <4>微信小程序的基础知识 2.实现原理 首先,先看一下这个请求函数 wx.request({ url: '******',

SpringMVC入门--编写一个SpringMVC小程序

一.SpringMVC的优势 Spring 为展现层提供的基于 MVC 设计理念的优秀的Web 框架,是目前最主流的 MVC 框架之一.Spring3.0 后全面超越 Struts2,成为最优秀的 MVC 框架.Spring MVC 通过一  套 MVC 注解,让 POJO 成为处理请求的控制器,而无须实现任何接口.支持 REST 风格的 URL 请求(GET POST PUT DELTE).采用了松散耦合可插拔组件结构,比其他 MVC      框架更具扩展性和灵活性..二.编写一个简单的Sp