主要实现录制功能的类: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="摄像"/>
</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="录制"/>
<Button
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止"/>
</LinearLayout>
</LinearLayout>
(4)首先需要给程序必要的权限才能读/写、访问Camera、录制音频文件、创建删除文件等权限。在程序的AndroidManifest.xml程序清单文件下添加如下权限:
读取Camera权限
<uses-permission android:name="android.permission.CAMERA" ></uses-permission>
视频录制权限
<span style="color:#ff0000;"><uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission></span>
读写内存卡权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
创建和删除文件目录权限
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
因为因为VideoRecord.java类是另一个Activity所以还需要在AndroidMainifest.xml文件中添加这样一段代码(一般这里的类名需要写完整的类结构):
<activity android:name=".VideoRecord"></activity>
(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) {
Intent intent=new Intent();
intent.setClass(MainActivity.this, VideoRecord.class); //intent对象指定的类
MainActivity.this.startActivity(intent); //启动新的Activity
}
});
}
@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();
}
//获取存储(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);
//初始化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
{
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(); //设置弹出提示框
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。
至此所有的摄像功能的介绍都已经结束了,录制视频需要考虑调用摄像头功能和音频录制功能。