主要实现录制功能的类:Camera类和MediaRecorder类。功能描写叙述:首先进入视频录制界面,点击录像button进入录像功能界面,点击录制開始录制视频, 点击停止button,将录制的视频存放到指定文件夹下存放。以下通过Samples_10_3程序实现详细功能:
(1)新建一个Android Application Project项目取名为Samples_10_3
(2)在res/layout文件改动activity_main.xml主布局文件(主要加入一个标题和摄像button)
<?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视图控件、摄像button和停止摄像button)
<?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的Button组件对象
stopButton=(Button)this.findViewById(R.id.stop); //实例化停止录制button的Button组件对象
startButton.setEnabled(true);
stopButton.setEnabled(false); //加入摄像button单击监听
startButton.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) {
// 调用開始摄像方法
startRecording();
}
});
//加入停止button单击监听
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); //開始录制button失效
stopButton.setEnabled(true); //停止录制button生效
}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); //摄像button生效
stopButton.setEnabled(false); //停止button生效 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()+"视频文件?"); //设置信息内容
//设置确认button,并加入button监听事件
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.点击摄像button进入视频预览功能:
C.点击录制button后视频文件被保存在MyVideo目录以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
D.MyVideo目录下录制好的文件:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
(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。