溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android仿微信錄制小視頻

發(fā)布時間:2020-10-26 04:30:41 來源:腳本之家 閱讀:191 作者:Anro丶 欄目:移動開發(fā)

本文實(shí)例為大家分享了Android仿微信錄制小視頻的具體代碼,供大家參考,具體內(nèi)容如下

先上張圖片看看效果

Android仿微信錄制小視頻

簡單敘述下

  • 首先通過Camera類調(diào)用系統(tǒng)相機(jī)
  • 通過surfaceview繪制出來
  • 通過MediaRecorder來錄制視頻
  • 閃光燈 和 切換攝像頭 需要重新配置Camera的參數(shù)
  • Camera預(yù)覽界面畫面拉升的原因是因?yàn)镾urfaceview的大小與設(shè)定的比例不一致的

**本次版本更新了 切換前置攝像頭錄制視頻問題
Android部分手機(jī)錄制視頻適配IOS手機(jī)問題 (OPPO手機(jī)部分不適配 目前啟用的H264格式)**

完整的代碼

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.media.MediaMetadataRetriever;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.tongxun.atongmu.dialog.CommonDialog;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class CircleViedoActivity extends Activity implements View.OnClickListener,MediaRecorder.OnErrorListener {

 private SurfaceView mSurfaceView;
 private SurfaceHolder mSurfaceHolder;
 private ProgressBar mProgressBar;
 private Button shoot_button;
 private ImageView circle_light_btn;
 private ImageView circle_change_camera_btn;
 private TextView circle_camera_time;

 private MediaRecorder mMediaRecorder;
 private Camera mCamera;
 private Timer mTimer;// 計(jì)時器
 private OnRecordFinishListener mOnRecordFinishListener;// 錄制完成回調(diào)接口
 private int mWidth;// 視頻分辨率寬度
 private int mHeight;// 視頻分辨率高度
 private boolean isOpenCamera;// 是否一開始就打開攝像頭
 private int mRecordMaxTime;// 一次拍攝最長時間
 private int mTimeCount;// 時間計(jì)數(shù)
 private int mNumberOfCameras=0;//手機(jī)攝像頭的數(shù)量
 Bitmap bitmap;//圖片縮略圖
 private int screenWidth;
 public static File mVecordFile = null;// 文件
 private boolean isOpenFlash=false;
 private boolean isBackCamera=true;
 private int mbackCamera;
 private int mfrontCamera;
 private CommonDialog commonDialog;

 private static final int MOVICE_SUCCESS=1000;//錄制完成
 private static final int MOVICE_FILE=1001;//錄制失敗


 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_super_video);
 init_datas();
 init_view();
 set_datas();
 init_event();
 }

 private void init_datas() {
 isOpenCamera=true;//默認(rèn)一開始就打開相機(jī)
 mRecordMaxTime=10;//設(shè)置錄制的時間

 //獲取手機(jī)攝像頭的數(shù)量
 Camera.CameraInfo cameraInfo=new Camera.CameraInfo();
 mNumberOfCameras=Camera.getNumberOfCameras();
 for(int camidx=0;camidx<mNumberOfCameras;camidx++){
  Camera.getCameraInfo(camidx, cameraInfo);
  if(cameraInfo.facing==Camera.CameraInfo.CAMERA_FACING_BACK){
  mbackCamera=camidx;
  }else if(cameraInfo.facing==Camera.CameraInfo.CAMERA_FACING_FRONT){
  mfrontCamera=camidx;
  }
 }



 }

 private void init_view() {
 mWidth=640;
 mHeight=480;

 //獲取屏幕的寬度
 screenWidth = getWindowManager().getDefaultDisplay().getWidth();
 mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview);//預(yù)覽界面
 mProgressBar = (ProgressBar) findViewById(R.id.progressBar);//進(jìn)度條
 shoot_button = (Button) findViewById(R.id.shoot_button);//拍攝按鈕
 circle_camera_time= (TextView) findViewById(R.id.circle_camera_time);
 circle_change_camera_btn= (ImageView) findViewById(R.id.circle_change_camera_btn);//切換攝像頭
 circle_light_btn= (ImageView) findViewById(R.id.circle_light_btn);//開啟閃光燈
 ViewGroup.LayoutParams params=mSurfaceView.getLayoutParams();
 params.height=(screenWidth*4)/3;
 params.width=screenWidth;
 mSurfaceView.setLayoutParams(params);


 top_model2_left_img= (ImageView)findViewById(R.id.top_model2_left_img);
 top_model2_left_img.setOnClickListener(this);
 top_model2_right_img= (ImageView)findViewById(R.id.top_model2_right_img);
 top_model2_right_img.setVisibility(View.INVISIBLE);
 top_model2_txt= (TextView)findViewById(R.id.top_model2_txt);
 top_model2_txt.setText("視頻錄制");
 }


 private void set_datas() {
 mSurfaceHolder = mSurfaceView.getHolder();
 mProgressBar.setMax(mRecordMaxTime);// 設(shè)置進(jìn)度條最大量
 mSurfaceHolder.setKeepScreenOn(true);//設(shè)置屏幕常亮
 mSurfaceHolder.addCallback(new CustomCallBack());
 mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 circle_camera_time.setText("");
 }

 private void init_event() {
 circle_light_btn.setOnClickListener(this);
 circle_change_camera_btn.setOnClickListener(this);
 shoot_button.setOnTouchListener(new View.OnTouchListener() {
  @Override
  public boolean onTouch(View v, MotionEvent event) {
  if (event.getAction() == MotionEvent.ACTION_DOWN) {
   record(new OnRecordFinishListener() {
   @Override
   public void onRecordFinish() {
    //錄制時間達(dá)到最大值
    handler.sendEmptyMessage(MOVICE_SUCCESS);
   }
   });
  } else if (event.getAction() == MotionEvent.ACTION_UP) {
   if (mTimeCount > 1 && mTimeCount<10) { //防止達(dá)到最大值up事件
   //錄制時間大于一秒
   handler.sendEmptyMessage(MOVICE_SUCCESS);
   } else if(mTimeCount<=1) {
   //刪除小于一秒的視頻
   if (getmVecordFile() != null) {
    getmVecordFile().delete();
   }
   handler.sendEmptyMessage(MOVICE_FILE);

   }
  }
  return true;
  }
 });
 }

 @Override
 protected void onResume() {
 super.onResume();
 if(mCamera!=null){
  freeCameraResource();
 }
 try {
  initCamera();
 } catch (IOException e) {
  e.printStackTrace();
 }
 }

 @Override
 public void onSaveInstanceState(Bundle outState) {
 super.onSaveInstanceState(outState);
 // mRecorderView.stop();
 }

 private Handler handler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
  //停止拍攝
  stopRecord();
  switch (msg.what){
  case MOVICE_SUCCESS:
   String msgs = "確認(rèn)上傳嗎?";
   commonDialog = new CommonDialog(CircleViedoActivity.this, new CommonDialog.GoCommonDialog() {
   @Override
   public void go() {
    finishActivity();
    commonDialog.dismiss();
   }
   @Override
   public void cancel() {
    //刪除沒有上傳的視頻
    if (getmVecordFile() != null) {
    getmVecordFile().delete();
    }
    commonDialog.dismiss();
   }
   }, msgs, "確定", "取消");
   commonDialog.show();


   break;
  case MOVICE_FILE:
   Toast.makeText(CircleViedoActivity.this, "視頻錄制時間太短", Toast.LENGTH_SHORT).show();
   break;
  }

 }
 };


 private void finishActivity() {
 stop();
 Bitmap bitmap = null;
 if (getmVecordFile() != null) {
  //得到文件 File類型
  File mfile = getmVecordFile();
  bitmap = getVideoThumbnail(mfile.toString());
 }

 /**
 * 部分Android手機(jī)縮略圖拉不到,找到一種解決辦法不是太滿意 有沒有大神提供思路
 */

 // VideoPlayerActivity.startActivity(this, mRecorderView.getVecordFile().toString());
 Intent intent = new Intent();
 intent.putExtra("bitmap",bitmap);
 setResult(RESULT_OK,intent);
 finish();
 }

 @Override
 public void onError(MediaRecorder mr, int what, int extra) {
 try {
  if (mr != null)
  mr.reset();
 } catch (IllegalStateException e) {
  e.printStackTrace();
 } catch (Exception e) {
  e.printStackTrace();
 }
 }

 @Override
 public void onClick(View v) {
 switch (v.getId()){
  case R.id.circle_light_btn:
  //開啟關(guān)閉閃光燈 默認(rèn)關(guān)閉
  if(isOpenFlash){
   isOpenFlash=false;
   circle_light_btn.setImageResource(R.drawable.camera_light);
  }else {
   isOpenFlash=true;
   circle_light_btn.setImageResource(R.drawable.camera_no_light);
  }
  try {
   initCamera();
  } catch (IOException e) {
   e.printStackTrace();
  }
  break;
  case R.id.circle_change_camera_btn:
  if(isBackCamera){
   isBackCamera=false;
  }else {
   isBackCamera=true;
  }
  try {
   initCamera();
  } catch (IOException e) {
   e.printStackTrace();
  }
  break;
  case R.id.top_model2_left_img:
  stop();
  finish();
  break;
 }
 }

 private class CustomCallBack implements SurfaceHolder.Callback {
 @Override
 public void surfaceCreated(SurfaceHolder holder) {
  if (!isOpenCamera)
  return;
  try {
  initCamera();
  } catch (IOException e) {
  e.printStackTrace();
  }
 }

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

 }

 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {

 }
 }
 /**
 * 初始化攝像頭
 */
 private void initCamera() throws IOException {
 if (mCamera != null) {
  freeCameraResource();
 }
 try {
  if(isBackCamera){
  mCamera = Camera.open(mbackCamera);//打開后攝像頭
  setCameraParams(isOpenFlash);
  }else {
  mCamera=Camera.open(mfrontCamera);//打開前攝像頭
  }
 } catch (Exception e) {
  e.printStackTrace();
  freeCameraResource();
 }
 if (mCamera == null)
  return;

 mCamera.setDisplayOrientation(90);
 mCamera.setPreviewDisplay(mSurfaceHolder);
 mCamera.startPreview();
 mCamera.unlock();
 }


 /**
 * 設(shè)置攝像頭為豎屏
 */
 private void setCameraParams(Boolean isOpenFlash) {
 if (mCamera != null) {
  Camera.Parameters params = mCamera.getParameters();
  //獲取預(yù)覽的各種分辨率
  List<Camera.Size> supportedPreviewSizes = params.getSupportedPreviewSizes();
  params.set("orientation", "portrait");//豎屏錄制
  params.setPreviewSize(mWidth, mHeight);//默認(rèn)640*480
  params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//持續(xù)對焦
  if(isBackCamera){
  if(isOpenFlash){
   //開啟閃光燈
   params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);

  }else {
   //關(guān)閉閃光燈
   params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
  }

  }else {

  }
  mCamera.setParameters(params);
 }
 }


 /**
 * 釋放攝像頭資源
 */
 private void freeCameraResource() {
 if (mCamera != null) {
  mCamera.setPreviewCallback(null);
  mCamera.stopPreview();
  mCamera.lock();
  mCamera.release();
  mCamera = null;
 }
 }

 private void createRecordDir() {
 File sampleDir = new File(Environment.getExternalStorageDirectory() + File.separator + "ATOMImg/video/");
 if (!sampleDir.exists()) {
  sampleDir.mkdirs();
 }
 File vecordDir = sampleDir;
 // 創(chuàng)建文件
 try {
  mVecordFile = File.createTempFile("recording", ".mp4", vecordDir);//mp4格式

 } catch (IOException e) {
 }
 }

 /**
 * 初始化
 */
 private void initRecord() throws IOException {
 mMediaRecorder = new MediaRecorder();
 mMediaRecorder.reset();
 if (mCamera != null)
  mMediaRecorder.setCamera(mCamera);
 mMediaRecorder.setOnErrorListener(this);
 mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
 mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);// 視頻源
 mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 音頻源
 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 視頻輸出格式
 mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);// 音頻格式
 mMediaRecorder.setVideoSize(mWidth, mHeight);// 設(shè)置分辨率:
 // mMediaRecorder.setVideoFrameRate(16);// 這個我把它去掉了,感覺沒什么用
 mMediaRecorder.setVideoEncodingBitRate(1 * 1024 * 1024);// 設(shè)置幀頻率,然后就清晰了
 if(isBackCamera) {
  mMediaRecorder.setOrientationHint(90);// 輸出旋轉(zhuǎn)90度,保持豎屏錄制
 }else {
  mMediaRecorder.setOrientationHint(270);
 }mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// 視頻錄制格式



----------


/**
 這里是配置攝像頭的重點(diǎn) 因?yàn)槲覀冧浿埔曨l需要適配IOS開發(fā)和Android不同版本的手機(jī) 而IOS和Android通配的視頻格式不多 我們這里采用H264格式 它的兼容范圍更廣闊 主要解決的就是部分OPPO手機(jī)不適配問題
*/


----------


 // mediaRecorder.setMaxDuration(Constant.MAXVEDIOTIME * 1000);
 mMediaRecorder.setOutputFile(mVecordFile.getAbsolutePath());
 mMediaRecorder.prepare();
 try {
  mMediaRecorder.start();
 } catch (IllegalStateException e) {
  e.printStackTrace();
 } catch (RuntimeException e) {
  e.printStackTrace();
 } catch (Exception e) {
  e.printStackTrace();
 }
 }

 /**
 * 錄制完成回調(diào)接口
 */
 public interface OnRecordFinishListener {
 public void onRecordFinish();
 }

 /**
 * 錄制
 * @param onRecordFinishListener
 */
 public void record(final OnRecordFinishListener onRecordFinishListener) {
 this.mOnRecordFinishListener = onRecordFinishListener;
 createRecordDir();//創(chuàng)建目錄

 try {
  if (!isOpenCamera)// 如果未打開攝像頭,則打開
  initCamera();//初始化攝像頭
  initRecord();//初始化錄制參數(shù)
  mTimeCount = 0;// 時間計(jì)數(shù)器重新賦值

  mTimer = new Timer();//創(chuàng)建一個定時器

  mTimer.schedule(new TimerTask() {

  @Override
  public void run() {
   // TODO Auto-generated method stub
   mTimeCount++;
   mProgressBar.setProgress(mTimeCount);// 設(shè)置進(jìn)度條
   // handler.sendEmptyMessage(TIME_CHANGW);
   runOnUiThread(new Runnable() {
   @Override
   public void run() {
    circle_camera_time.setText(mTimeCount + "″");
   }
   });
   if (mTimeCount == mRecordMaxTime) {// 達(dá)到指定時間,停止拍攝
   //錄制完成調(diào)用錄制回調(diào)接口
   if (mOnRecordFinishListener != null)
    mOnRecordFinishListener.onRecordFinish();
   }
  }
  }, 0, 1000);
 } catch (IOException e) {
  e.printStackTrace();
 }
 }
 /**
 * 停止拍攝
 */
 public void stop() {
 stopRecord();
 releaseRecord();
 freeCameraResource();
 }

 /**
 * 停止錄制
 */
 public void stopRecord() {
 mProgressBar.setProgress(0);
 circle_camera_time.setText("");
 if (mTimer != null)
  mTimer.cancel();
 if (mMediaRecorder != null) {
  // 設(shè)置后不會崩
  mMediaRecorder.setOnErrorListener(null);
  mMediaRecorder.setPreviewDisplay(null);
  try {
  mMediaRecorder.stop();
  } catch (IllegalStateException e) {
  e.printStackTrace();
  } catch (RuntimeException e) {
  e.printStackTrace();
  } catch (Exception e) {
  e.printStackTrace();
  }
 }
 }

 /**
 * 獲取的視頻的位置
 * @return
 */
 public File getmVecordFile() {
 return mVecordFile;
 }

 /**
 * 釋放資源
 */
 private void releaseRecord() {
 if (mMediaRecorder != null) {
  mMediaRecorder.setOnErrorListener(null);
  try {
  mMediaRecorder.release();
  } catch (IllegalStateException e) {
  e.printStackTrace();
  } catch (Exception e) {
  e.printStackTrace();
  }
 }
 mMediaRecorder = null;
 }

 @Override
 public boolean onKeyDown(int keyCode, KeyEvent event) {
 if ((keyCode == KeyEvent.KEYCODE_BACK)) {
  stop();
  finish();
  return false;
 }else {
  return super.onKeyDown(keyCode, event);
 }

 }

 /**
 * 獲取視頻縮略圖
 * @param filePath
 * @return
 */
 public Bitmap getVideoThumbnail(String filePath) {
 Bitmap bitmap = null;
 MediaMetadataRetriever retriever = new MediaMetadataRetriever();
 try {
  retriever.setDataSource(filePath);
  bitmap = retriever.getFrameAtTime();
 }
 catch(IllegalArgumentException e) {
  e.printStackTrace();
 }
 catch (RuntimeException e) {
  e.printStackTrace();
 }
 finally {
  try {
  retriever.release();
  }
  catch (RuntimeException e) {
  e.printStackTrace();
  }
 }
 return bitmap;
 }

 @Override
 protected void onDestroy() {
 super.onDestroy();
 if(bitmap!=null){
  try {
  bitmap.recycle();
  } catch (Exception e) {
  e.printStackTrace();
  }
  bitmap=null;
 }

 }
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI