Android系統自帶的MediaRecorder結合Camera實現視訊錄製及播放功能。
阿新 • • 發佈:2018-11-02
近期,公司專案新增了需求,需要視訊錄製,然後儲存到本地,再播放...。
看了很多其他的框架,說不出好壞,應該說各有千秋吧。但我覺得還是原生的靠譜,就是谷歌系統自帶的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" /> <ImageViewandroid: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>