Android视频录制、播放的两种方式
1、通过Intent的方式:Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
2、使用Camera的API,调用Media的MediaRecorder。
Intent的方式
注意:这里播放camera录制的视频使用VideoView,不使用MediaPlayer和SurfaceView的结合。用帧布局Framelayout布局,VideoView和ImageView,播放时隐藏视频缩略图,暂停时或初始化时显示视频缩略图。
因为VideoView没有设置监听播放和暂停状态的事件,所以我自定义一个CustomVideoView继承了VideoView,在里面创建一个监听方法和重写VideoView的播放、暂停的方法。
使用相机intent获取视频是使用最少代码使得你的应用获取视频的捷径.一个视频获取intent可以包含以下额外信息:
MediaStore.EXTRA_OUTPUT-此设置需要一个保存视频的路径和文件名的Uri.此设置是可选的但是强列推荐的.如果你不指定此值,相机应用就把请求到的图像以默认的文件名保存到默认的文件夹下,这些信息保存在返回的intent的Intent.getData()字段中.
MediaStore.EXTRA_VIDEO_QUALITY- 此值在最低质量最小文件尺寸时是0,在最高质量最大文件尺寸时是1.
MediaStore.EXTRA_DURATION_LIMIT- 此值设置获取视频的长度,以秒为单位.
MediaStore.EXTRA_SIZE_LIMIT- 此值设置获取视频文件的大小,以字节为单位.
XML布局视图:
public class MainActivity extends AppCompatActivity {
private static int REQUST_VIDEO = 1;
private Button btn;
private Button btn_start;
private FrameLayout fl;
private CustomVideoView video;
private ImageView iv;
private String sdCard;
private String videoPath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init(){
btn = ((Button) findViewById(R.id.btn_recoder));
btn_start = ((Button) findViewById(R.id.btn_start));
fl = ((FrameLayout) findViewById(R.id.fl_video));
video = ((CustomVideoView) findViewById(R.id.video));
iv = ((ImageView) findViewById(R.id.iv));
sdCard = Environment.getExternalStorageDirectory().getPath();
String currenTimeMillis = new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date(System.currentTimeMillis()));
videoPath = sdCard + "/" + "0000.mp4";
MediaController controller = new MediaController(this);
video.setMediaController(controller);
if (video.isPlaying()){
iv.setVisibility(View.INVISIBLE);
}
video.setPlayPauseListener(new CustomVideoView.PlayPauseListener() {
@Override
public void onPlay() {
Toast.makeText(MainActivity.this,"播放",Toast.LENGTH_SHORT).show();
iv.setVisibility(View.INVISIBLE);
}
@Override
public void onPause() {
Toast.makeText(MainActivity.this,"暂停",Toast.LENGTH_SHORT).show();
iv.setVisibility(View.VISIBLE);
}
});
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,videoPath);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY,1);
startActivityForResult(intent,REQUST_VIDEO);
}
});
}
private Bitmap getVideoBitmap(String videoPath){
MediaMetadataRetriever retriever = null;
try {
retriever = new MediaMetadataRetriever();
retriever.setDataSource(videoPath);
Bitmap bitmap = retriever.getFrameAtTime();
return bitmap;
}finally {
retriever.release();
}
}
private Bitmap getVideoBitmap2(Uri uri){
MediaMetadataRetriever retriever = null;
try {
retriever = new MediaMetadataRetriever();
retriever.setDataSource(this,uri);
Bitmap bitmap = retriever.getFrameAtTime();
return bitmap;
}finally {
retriever.release();
}
}
public void start(View view){
iv.setVisibility(View.INVISIBLE);
video.start();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK){
if (requestCode == REQUST_VIDEO){
fl.setVisibility(View.VISIBLE);
btn_start.setVisibility(View.VISIBLE);
Uri uri = data.getData();
video.setVideoURI(uri);
// Bitmap bitmap = getVideoBitmap(videoPath);
Bitmap bitmap = getVideoBitmap2(uri);
iv.setImageBitmap(bitmap);
}
}
}
}
//自定义VideoView
public class CustomVideoView extends VideoView {
private PlayPauseListener listener;
public CustomVideoView(Context context) {
super(context);
}
public CustomVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setPlayPauseListener(PlayPauseListener listener){
this.listener = listener;
}
@Override
public void pause() {
super.pause();
if (listener!=null){
listener.onPause();
}
}
@Override
public void start() {
super.start();
if (listener!=null){
listener.onPlay();
}
}
interface PlayPauseListener{
void onPlay();
void onPause();
}
}
最终Intent方式的效果图:
DEMO下载(百度云):
http://pan.baidu.com/s/1c1Nsbqo
提取码:yydc
方式二-MediaRecorder
权限:
例子中先用mediarecorder录制保存一个视频然后播放看看效果,点击“跳转”可以调到第二个Main2Activity中,用VideoView播放刚才录制的视频,Main2Activity主要测试如何播放在本地手机的视频。
XML布局:(MainActivity)
代码:
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{
private static final String TAG = "MainActivity";
private SurfaceView mSurfaceview;
private Button btn_start_or_stop;
private Button btn_play;
private Button btn_turnto;
private boolean isRecording = false;//是否正在录像
private boolean isPlay = false;//是否正在播放录像
private MediaRecorder mRecorder;
private SurfaceHolder mSurfaceHolder;
private ImageView mImageView;
private Camera camera;
private MediaPlayer mediaPlayer;
private String path;
private TextView time;
private int text = 0;
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
@Override
public void run() {
text++;
time.setText("录制"+text+"秒");
handler.postDelayed(this,1000);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mSurfaceview = (SurfaceView) findViewById(R.id.surfaceview);
mImageView = (ImageView) findViewById(R.id.imageview);
btn_start_or_stop = (Button) findViewById(R.id.btn_start_or_stop);
btn_turnto = (Button) findViewById(R.id.btn_turnto);
btn_play = (Button) findViewById(R.id.btn_play);
time = (TextView)findViewById(R.id.time);
btn_turnto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (path != null){
File file = new File(path);
if(file.exists()){
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
intent.putExtra("path",path);
startActivity(intent);
}else {
Toast.makeText(MainActivity.this,"视频文件不存在",Toast.LENGTH_SHORT).show();
}
}else {
Toast.makeText(MainActivity.this,"文件路径不存在",Toast.LENGTH_SHORT).show();
}
}
});
btn_start_or_stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isPlay){
if (mediaPlayer != null){
isPlay = false;
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
}
if (!isRecording){
handler.postDelayed(runnable,1000);
mImageView.setVisibility(View.GONE);
if (mRecorder == null){
mRecorder = new MediaRecorder();// 创建mediarecorder对象
text = 0;//当点击停止之后,每一次进到这里都要重置录制的时间数
}
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
if (camera != null){
camera.setDisplayOrientation(90);//摄像图旋转90度
camera.unlock();
mRecorder.setCamera(camera);// 设置录制视频源为Camera(相机)
}
try{
mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); // 这两项需要放在setOutputFormat之前
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 这两项需要放在setOutputFormat之前
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//设置录制视频的输出格式
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//设置音频编码格式
mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);//设置视频编码格式// 设置录制的视频编码h263 h264
mRecorder.setVideoSize(640,480);//设置视频的分辨率,必须放在设置编码和格式的后面,否则报错
mRecorder.setVideoFrameRate(30);//这是设置视频录制的帧率,即1秒钟30帧。。必须放在设置编码和格式的后面,否则报错
mRecorder.setVideoEncodingBitRate(4 * 1024 * 1024);//这个属性很重要,这个也直接影响到视频录制的大小,这个设置的越大,视频越清晰
mRecorder.setOrientationHint(90);//视频旋转90度
mRecorder.setMaxDuration(30 * 1000);//设置录制最长时间为30秒
mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());//设置录制视频时的预览画面
path = getSdPath();
if (path != null){
File dir = new File(path + "/recordtest");
if (!dir.exists()){
dir.mkdir();
}
path = dir + "/" + getDate() + ".mp4";
mRecorder.setOutputFile(path);// 设置视频文件输出的路径
mRecorder.prepare();// 准备录制
mRecorder.start();// 开始录制
isRecording = true;
btn_start_or_stop.setText("停止");
}
}catch (Exception e){
e.printStackTrace();
}
}else {
if (isRecording){
try {
handler.removeCallbacks(runnable);
mRecorder.stop();// 停止录制
mRecorder.reset();// 恢复到未初始化的状态
mRecorder.release();// 释放资源
mRecorder = null;
btn_start_or_stop.setText("开始");
if (camera != null){
camera.release();
camera = null;
}
}catch (Exception e){
e.printStackTrace();
}
isRecording = false;
}
}
}
});
btn_play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isPlay = true;
mImageView.setVisibility(View.GONE);
if (mediaPlayer == null){
mediaPlayer = new MediaPlayer();
}
mediaPlayer.reset();
Uri uri = Uri.parse(path);
if (uri == null){
Toast.makeText(MainActivity.this,"请先录制视频",Toast.LENGTH_SHORT).show();
return;
}
mediaPlayer = MediaPlayer.create(MainActivity.this,uri);//使用mediaplayer播放uri视频
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);//设置播放流媒体类型。
mediaPlayer.setDisplay(mSurfaceHolder);// 设置屏幕
try{
mediaPlayer.prepare();
}catch (Exception e){
e.printStackTrace();
}
mediaPlayer.start();
}
});
SurfaceHolder holder = mSurfaceview.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
protected void onResume() {
super.onResume();
if (!isRecording){
mImageView.setVisibility(View.VISIBLE);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mSurfaceHolder = holder;
}
/**
* 获取系统时间
*
* @return
*/
private static String getDate(){
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
int minute = calendar.get(Calendar.MINUTE);
int hour = calendar.get(Calendar.HOUR);
int second = calendar.get(Calendar.SECOND);
String date = "" + year + (month + 1) + day + hour + minute + second;
return date;
}
/**
* 获取SD path
*
* @return
*/
public String getSdPath(){
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);//判断sd卡是否存在
if (sdCardExist){
sdDir = Environment.getExternalStorageDirectory();//获取根目录
return sdDir.toString();
}
return null;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// 将holder,这个holder为开始在onCreate里面取得的holder,将它赋给mSurfaceHolder
mSurfaceHolder = holder;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// surfaceDestroyed的时候同时对象设置为null
mSurfaceview = null;
mSurfaceHolder = null;
handler.removeCallbacks(runnable);
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (camera != null) {
camera.release();
camera = null;
}
if (mediaPlayer != null){
mediaPlayer.release();
mediaPlayer = null;
}
}
}
效果图:
MAin2Activity
XML布局(MAin2Activity)
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="project.wgc.mymediarecordertest01.Main2Activity">
android:layout_width="300dp"
android:layout_height="400dp"
/>
Main2Activity代码:
public class Main2Activity extends AppCompatActivity {
private Button play;
private VideoView video;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
video = ((VideoView) findViewById(R.id.video));
Intent intent = getIntent();
String path = intent.getStringExtra("path");
//Uri uri = Uri.parse(path);//第一种。把路径转换为uri,然后给videoview设置,
// video.setVideoURI(uri);
video.setVideoPath(path);//第二种,直接把本地视频的路径设置给VideoView也可以.
play = ((Button) findViewById(R.id.btn_play));
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
video.start();
}
});
}
}
效果图:
DEMO下载(百度云):
http://pan.baidu.com/s/1pLPTEPH
提取码:z3ul