主要实现录制功能的类: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。
至此所有的摄像功能的介绍都已经结束了,录制视频需要考虑调用摄像头功能和音频录制功能。
版权声明:本文为博主原创文章,未经博主允许不得转载。