1. 程式人生 > >Android系統自帶的MediaRecorder結合Camera實現視訊錄製及播放功能。

Android系統自帶的MediaRecorder結合Camera實現視訊錄製及播放功能。

    近期,公司專案新增了需求,需要視訊錄製,然後儲存到本地,再播放...。

看了很多其他的框架,說不出好壞,應該說各有千秋吧。但我覺得還是原生的靠譜,就是谷歌系統自帶的MediaRecorder。

不多說上程式碼吧(已經測試,沒問題)。

程式碼沒什麼複雜的,都是些基本的邏輯問題,註釋就比較少,理清邏輯就很簡單了。大家可以考去看看效果


佈局檔案:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"> <SurfaceView android:id="@+id/surfaceview" android:layout_width="match_parent" android:layout_marginBottom="60dp" android:layout_height="match_parent" /> <ImageView
android:id="@+id/imageview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="60dp" android:scaleType="centerCrop" android:src="@drawable/im"/> <Button android:id="@+id/btnStartStop" android
:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true" android:onClick="onStartStopPlay" android:text="開始/結束錄製"/> <Button android:id="@+id/btnPlayVideo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_toRightOf="@id/btnStartStop" android:text="播放" android:onClick="onStartStopPlay" android:layout_marginLeft="20dp"/> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="25sp" android:text="00:00" android:layout_alignParentBottom="true" android:layout_marginBottom="12dp" android:layout_marginLeft="20dp"/> </RelativeLayout>


java程式碼:


 
package com.example.tsx.mediarecorder;

import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.util.Calendar;

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
    private SurfaceView mSurfaceview;
    private ImageView mImageView;
    private Button mBtnStartStop;
    private Button mBtnPlay;
    private TextView mTextView;
    private boolean mIsPlay = false;//是否正在播放
    private boolean mStartedFlg = false;//是否正在錄影
    private MediaPlayer mediaPlayer;//多媒體播放器
    private int text = 0;
    private MediaRecorder mRecorder;//多媒體錄音
    private Camera mCamera;//相機
    private String path;//視訊儲存路徑
    private SurfaceHolder mSurfaceHolder;
    private android.os.Handler handler = new android.os.Handler();//android.os  是一個移動裝置,智慧手機和平板電腦的作業系統

    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            text++;
            mTextView.setText(text + "");
            handler.postDelayed(this, 1000);//休眠1秒
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);// 設定全屏
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        setContentView(R.layout.activity_main);

        intView();
        SurfaceHolder holder = mSurfaceview.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//緩衝區


    }

    @Override
    protected void onResume() {
        super.onResume();
       /* if (!mStartedFlg) {
            mImageView.setVisibility(View.GONE);
        }*/

    }

    private void intView() {
        mSurfaceview = (SurfaceView) findViewById(R.id.surfaceview);
        mImageView = (ImageView) findViewById(R.id.imageview);
        mBtnStartStop = (Button) findViewById(R.id.btnStartStop);
        mBtnPlay = (Button) findViewById(R.id.btnPlayVideo);
        mTextView = (TextView) findViewById(R.id.text);

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mSurfaceHolder = holder;

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        mSurfaceHolder = holder;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mSurfaceview = null;
        mSurfaceHolder = null;
        handler.removeCallbacks(runnable);
        if (mRecorder != null) {
            mRecorder.release();
            mRecorder = null;
        }
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

    public void onStartStopPlay(View view) {
        switch (view.getId()) {
            case R.id.btnStartStop:
                if (mIsPlay) {
                    if (mediaPlayer != null) {
                        mIsPlay = false;
                        mediaPlayer.stop();//停止媒體播放器
                        mediaPlayer.reset();//重置媒體播放器
                        mediaPlayer.release();//釋放資源
                        mediaPlayer = null;
                    }
                }
                //如果正在錄影
                if (!mStartedFlg) {
                    handler.postDelayed(runnable, 1000);
                    mImageView.setVisibility(View.GONE);
                    if (mRecorder == null) {
                        mRecorder = new MediaRecorder();
                    }
                    mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
                    if (mCamera != null) {
                        mCamera.setDisplayOrientation(90);
                        mCamera.unlock();
                        mRecorder.setCamera(mCamera);
                    }
                    try {
                     // 這兩項需要放在setOutputFormat之前,設定音訊和視訊的來源
             mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);//攝錄影機
             mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);//相機

                // Set output file format
             mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//輸出格式 mp4

             // 這兩項需要放在setOutputFormat之後  設定編碼器
            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//音訊編碼格式
            mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);//視訊編碼格式

                        mRecorder.setVideoSize(640, 480);//視訊解析度
                        mRecorder.setVideoFrameRate(30);//幀速率
                        mRecorder.setVideoEncodingBitRate(3 * 1024 * 1024);//視訊清晰度
                        mRecorder.setOrientationHint(90);//輸出視訊播放的方向提示
                        //設定記錄會話的最大持續時間(毫秒)
                        mRecorder.setMaxDuration(30 * 1000);
                        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();//開始
                            mStartedFlg = true;//錄影開始
                            mBtnStartStop.setText("結束錄製");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                //停止
                else {
                    if (mStartedFlg) {
                        handler.removeCallbacks(runnable);
                        mRecorder.stop();//停止
                        mRecorder.reset();//重置,設定為空閒狀態
                        mRecorder.release();//釋放
                        mRecorder = null;
                        mBtnStartStop.setText("開始錄製");
                        text = 0;
                        //釋放相機
                        if (mCamera != null) {
                            mCamera.release();
                            mCamera = null;
                        }
                    }
                    mStartedFlg = false;
                }
                break;

            case R.id.btnPlayVideo:
                if (mStartedFlg){
           Toast.makeText(MainActivity.this, "正在錄製,請結束錄製再播放"
                                Toast.LENGTH_SHORT).show();
                }else {

                    if (mediaPlayer == null) {
                        mediaPlayer = new MediaPlayer();
                    }
                    mediaPlayer.reset();
                    if (path == null) {
         Toast.makeText(MainActivity.this, "暫無視訊資源", Toast.LENGTH_SHORT).show();
                    } else {
                        mImageView.setVisibility(View.GONE);
                        Uri uri = Uri.parse(path);
                        mediaPlayer = MediaPlayer.create(MainActivity.this, uri);
                        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                        mediaPlayer.setDisplay(mSurfaceHolder);//設定顯示的控制元件
                        try {
                            mediaPlayer.prepare();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                  /*  int currentPosition = mediaPlayer.getCurrentPosition();
                    int duration = mediaPlayer.getDuration();
                    Log.i("time",currentPosition+"---"+duration);*/
                        mediaPlayer.start();
                        mBtnPlay.setText("暫停");
                        //監聽播放器是否播放結束
        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                            @Override
                            public void onCompletion(MediaPlayer mp) {
                                mImageView.setVisibility(View.VISIBLE);
                                mBtnPlay.setText("播放");
               Toast.makeText(MainActivity.this, "播放完畢",
                                        Toast.LENGTH_SHORT).show();
                            }
                        });

                    }
                }
                break;
        }
    }

    //獲取系統時間 視訊儲存的時間
    public static String getDate() {
        Calendar mCalendar = Calendar.getInstance();
        int year = mCalendar.get(Calendar.YEAR);
        int month = mCalendar.get(Calendar.MONTH);
        int day = mCalendar.get(Calendar.DATE);
        int hour = mCalendar.get(Calendar.HOUR);
        int minute = mCalendar.get(Calendar.MINUTE);
        int second = mCalendar.get(Calendar.SECOND);
        String date = "" + year + (month + 1) + day + hour + minute + second;
        Log.d("date", "date:" + date);
        return date;
    }

    //獲取SD卡路徑
    public String getSDPath() {
        File sdDir = null;
        // 判斷sd卡是否存在
        boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
        if (sdCardExist) {
            sdDir = Environment.getExternalStorageDirectory();//獲取根目錄
            return sdDir.toString();
        }
        return null;
    }

}

   

  另外不要忘了新增下面許可權


<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.CAMERA" >
</uses-permission>
<uses-permission android:name="android.permission.RECORD_AUDIO" >
</uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
</uses-permission>