android視訊錄製,播放;surfaceview+mediaPlayer播放視訊有聲音無影象的問題
阿新 • • 發佈:2019-01-02
1,功能說明:模仿QQ錄製視訊介面,可以傳入路徑播放(一定要在surfaceChanged);也可以錄製視訊並播放
,或者傳送(通過setResult返回值)
2,遇到的坑:通過傳入路徑播放的話,一定要讓surfaceview在圖層上顯示出來,不能被其他view遮擋,否則會出現有聲音無影象的現象
java程式碼
import java.io.File; import java.util.Calendar; import com.dami.student.MyApplication; import com.dami.student.R; import android.app.Activity; 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.content.Intent; import android.os.Environment; import android.util.Log; import android.view.View; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.content.Context; import android.view.MotionEvent; import com.dami.student.ui.chatui.widget.CircleImageView; import android.view.View.OnTouchListener; import android.view.Window; import android.view.View; import android.view.View.OnClickListener; import com.dami.student.net.utils.LogUtil; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class ShootingActivity extends Activity implements SurfaceHolder.Callback,OnClickListener,OnTouchListener{ private static final String TAG = "MainActivity"; private final int RESULT_SHOOTNG = 4; private LinearLayout LL_top; private LinearLayout LL_bottom; private SurfaceView mSurfaceview; private Button mBtnsend; private Button mBtnResetShooting; private CircleImageView mCircleImageView; private boolean mIsPlay = false;// 是否正在播放錄影 private MediaRecorder mRecorder; private SurfaceHolder mSurfaceHolder; private ImageView mExitShootingIM; private Camera camera; private MediaPlayer mediaPlayer; private String path = null; private String videoPath; private TextView mTimeTV; private int time = 0; private android.os.Handler handler = new android.os.Handler(); private Runnable runnable = new Runnable() { @Override public void run() { time++; mTimeTV.setText(time + ""); handler.postDelayed(this, 1000); } }; @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_shooting); inIt(); } @Override protected void onResume() { super.onResume(); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.btnsend: Intent intent = new Intent(); intent.putExtra("data", path); setResult(-1, intent); finish(); break; case R.id.exit_shooting_IM: finish(); break; case R.id.btn_reset_shooting: resetShooting(); break; case R.id.surfaceview: finish(); break; default: break; } } @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.start_shooting: if (event.getAction() == MotionEvent.ACTION_DOWN) { startShooting(); }else if (event.getAction() == MotionEvent.ACTION_UP) { StopShooting(); playVideo(path); } break; default: break; } return true; } @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { mSurfaceHolder = surfaceHolder; LogUtil.i(TAG, "wdh surfaceCreated path "+path); if (null == videoPath) { camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK); if (camera != null) { try { camera.setPreviewDisplay(mSurfaceHolder); camera.setDisplayOrientation(90); camera.startPreview(); } catch (Exception e) { // TODO: handle exception LogUtil.i(TAG, "wdh surfaceCreated"+e); } } } } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { // 將holder,這個holder為開始在onCreate裡面取得的holder,將它賦給mSurfaceHolder LogUtil.i(TAG, "wdh -----------------surfaceChanged"); mSurfaceHolder = surfaceHolder; if (null != videoPath) {//傳進來路徑播放 playVideo(videoPath); } } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { mSurfaceview = null; mSurfaceHolder = null; handler.removeCallbacks(runnable); if (mRecorder != null) { mRecorder.release(); mRecorder = null; Log.d(TAG, "surfaceDestroyed release mRecorder"); } if (camera != null) { camera.release(); camera = null; } if (mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; } } private void inIt() { // TODO Auto-generated method stub LL_top = (LinearLayout)findViewById(R.id.LL_top); LL_bottom = (LinearLayout)findViewById(R.id.LL_bottom); mSurfaceview = (SurfaceView) findViewById(R.id.surfaceview); mExitShootingIM = (ImageView) findViewById(R.id.exit_shooting_IM); mExitShootingIM.setOnClickListener(this); mBtnResetShooting = (Button) findViewById(R.id.btn_reset_shooting); mBtnResetShooting.setOnClickListener(this); mBtnsend = (Button) findViewById(R.id.btnsend); mBtnsend.setOnClickListener(this); mTimeTV = (TextView) findViewById(R.id.time_TV); mCircleImageView = (CircleImageView)findViewById(R.id.start_shooting); mCircleImageView.setOnTouchListener(this); videoPath = getIntent().getStringExtra("videoPath"); LogUtil.i(TAG, "wdh videoPath"+videoPath); if (null != videoPath) { LL_top.setVisibility(View.GONE); LL_bottom.setVisibility(View.GONE); mSurfaceview.setOnClickListener(this); }else { LL_top.setVisibility(View.VISIBLE); LL_bottom.setVisibility(View.VISIBLE); } SurfaceHolder holder = mSurfaceview.getHolder(); holder.addCallback(this); // setType必須設定,要不出錯. holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } /** * 開始播放 * */ private void playVideo(String videoPath){ LogUtil.i(TAG, "wdh -----------------playVideo"); mIsPlay = true; if (mediaPlayer == null) { mediaPlayer = new MediaPlayer(); } mediaPlayer.reset(); Uri uri = Uri.parse(videoPath); mediaPlayer = MediaPlayer.create(ShootingActivity.this, uri); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setDisplay(mSurfaceHolder); try { mediaPlayer.prepare(); } catch (Exception e) { e.printStackTrace(); } mediaPlayer.start(); mediaPlayer.setLooping(true);//設定重複播放 } /** * 獲取系統時間 * * @return */ public static String getDate() { Calendar ca = Calendar.getInstance(); int year = ca.get(Calendar.YEAR); // 獲取年份 int month = ca.get(Calendar.MONTH); // 獲取月份 int day = ca.get(Calendar.DATE); // 獲取日 int minute = ca.get(Calendar.MINUTE); // 分 int hour = ca.get(Calendar.HOUR); // 小時 int second = ca.get(Calendar.SECOND); // 秒 String date = "" + year + (month + 1) + day + hour + minute + second; Log.d(TAG, "date:" + date); return date; } /** * 開始錄製 * */ private void startShooting(){ mTimeTV.setVisibility(View.VISIBLE); mCircleImageView.setVisibility(View.VISIBLE); mBtnsend.setVisibility(View.INVISIBLE); mBtnResetShooting.setVisibility(View.INVISIBLE); if (mIsPlay) { if (mediaPlayer != null) { mIsPlay = false; mediaPlayer.stop(); mediaPlayer.reset(); mediaPlayer.release(); mediaPlayer = null; } } handler.postDelayed(runnable, 1000); if (mRecorder == null) { mRecorder = new MediaRecorder(); } camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK); if (camera != null) { camera.setDisplayOrientation(90); camera.unlock(); mRecorder.setCamera(camera); } try { // 這兩項需要放在setOutputFormat之前 mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // Set output file format mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 這兩項需要放在setOutputFormat之後 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); mRecorder.setVideoSize(640, 480); mRecorder.setVideoFrameRate(30); mRecorder.setVideoEncodingBitRate(3 * 1024 * 1024); mRecorder.setOrientationHint(90); // 設定記錄會話的最大持續時間(毫秒) mRecorder.setMaxDuration(10 * 1000); mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); path = MyApplication.LOCAL_FILE_PATH; 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(); } } catch (Exception e) { e.printStackTrace(); } } /** * 停止錄製 * */ private void StopShooting(){ mTimeTV.setVisibility(View.INVISIBLE); mBtnsend.setVisibility(View.VISIBLE); mBtnResetShooting.setVisibility(View.VISIBLE); mCircleImageView.setVisibility(View.INVISIBLE); // stop try { handler.removeCallbacks(runnable); mRecorder.stop(); mRecorder.reset(); mRecorder.release(); mRecorder = null; time = 0; if (camera != null) { camera.release(); camera = null; } } catch (Exception e) { e.printStackTrace(); } } /** * 重新錄製 * */ private void resetShooting(){ time = 0; mTimeTV.setText(time + ""); mTimeTV.setVisibility(View.VISIBLE); mCircleImageView.setVisibility(View.VISIBLE); mBtnsend.setVisibility(View.INVISIBLE); mBtnResetShooting.setVisibility(View.INVISIBLE); if (mIsPlay) { if (mediaPlayer != null) { mIsPlay = false; mediaPlayer.stop(); mediaPlayer.reset(); mediaPlayer.release(); mediaPlayer = null; } } if (mRecorder != null) { mRecorder.release(); mRecorder = null; } if (null == camera) { camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK); } if (camera != null) { try { camera.setPreviewDisplay(mSurfaceHolder); camera.setDisplayOrientation(90); camera.startPreview(); } catch (Exception e) { // TODO: handle exception LogUtil.i(TAG, "wdh surfaceCreated"+e); } } } }
佈局檔案:
原文地址:http://blog.csdn.net/woshizisezise/article/details/51878566<?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_height="match_parent" /> <ImageView android:id="@+id/imageview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="60dp" android:visibility="gone" android:src="@drawable/ic_launcher"/> <Button android:id="@+id/btnStartStop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true" android:text="@string/shooting_start"/> <Button android:id="@+id/btnPlayVideo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_toLeftOf="@id/btnStartStop" android:text="@string/play" android:layout_marginRight="20dp"/> <Button android:id="@+id/btnsend" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_toRightOf="@id/btnStartStop" android:text="@string/send" android:layout_marginLeft="20dp"/> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="25sp" android:textColor="@color/white" android:text="@string/time_start" android:layout_alignParentTop="true" android:layout_marginTop="12dp" android:layout_marginLeft="20dp" android:layout_centerHorizontal="true"/> </RelativeLayout>