package com.client.tok.ui.video; import android.app.Activity; import android.content.Intent; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.content.FileProvider; import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.VideoView; import com.client.tok.R; import com.client.tok.base.BaseTitleFullScreenActivity; import com.client.tok.media.recorder.video.CameraGLView; import com.client.tok.media.recorder.video.MediaAudioEncoder; import com.client.tok.media.recorder.video.MediaEncoder; import com.client.tok.media.recorder.video.MediaMuxerWrapper; import com.client.tok.media.recorder.video.MediaVideoEncoder; import com.client.tok.pagejump.GlobalParams; import com.client.tok.pagejump.IntentConstants; import com.client.tok.permission.PermissionCallBack; import com.client.tok.permission.PermissionModel; import com.client.tok.utils.FileUtilsJ; import com.client.tok.utils.LogUtil; import com.client.tok.utils.StorageUtil; import com.client.tok.utils.ViewUtil; import com.client.tok.widget.RoundProgress; import java.io.File; import java.io.IOException; import java.util.List; public class VideoRecordActivity extends BaseTitleFullScreenActivity implements View.OnClickListener, RoundProgress.ProgressListener { private String TAG = "VideoRecordActivity_"; // for camera preview display private CameraGLView mCameraGlView; private VideoView mVideoView; //muxer for audio/video recording private MediaMuxerWrapper mMuxer; private FrameLayout mCameraLayout; //button for start/stop recording private ImageView mFlashIv; private ImageView mRecordIv; private RoundProgress mProgressView; private ImageView mCameraIv; private ImageView mCloseIv; private ImageView mDropIv; private ImageView mSelectIv; private String[] FLASH_MODES = new String[] { CameraGLView.FLASH_OFF, CameraGLView.FLASH_ON }; private int[] FLASH_MODE_IMGS = new int[] { R.drawable.flash_off, R.drawable.flash_on }; private int[] CAMERA_IDS = new int[] { CameraGLView.CAMERA_BACK, CameraGLView.CAMERA_FRONT }; private int[] CAMERA_ID_IMGS = new int[] { R.drawable.camera_back, R.drawable.camera_front }; private int mCurFlashModeIndex = 0; private int mCurCameraIdIndex = 0; private boolean mIsRecording; private String mVideoPath; private String[] mPermission = PermissionModel.PERMISSION_CAMERA_AUDIO; private boolean mHasPermission; private boolean mHasShow; private Intent mIntent; private Handler mHandler = new Handler(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_record); mIntent = getIntent(); mCameraLayout = $(R.id.id_video_gl_view_layout); initCameraGlView(); mVideoView = $(R.id.id_video_view); mRecordIv = $(R.id.id_video_record_view); mRecordIv.setOnTouchListener(new RecordTouchListener()); mProgressView = $(R.id.id_record_progress); mProgressView.setAutoTimeProgress(GlobalParams.MAX_VIDEO_TIME); mProgressView.setProgressListener(this); mFlashIv = $(R.id.id_video_flash_iv); mFlashIv.setOnClickListener(this); mCameraIv = $(R.id.id_video_camera_iv); mCameraIv.setOnClickListener(this); mCloseIv = $(R.id.id_video_close_iv); mCloseIv.setOnClickListener(this); mDropIv = $(R.id.id_video_drop_iv); mDropIv.setOnClickListener(this); mSelectIv = $(R.id.id_video_select_iv); mSelectIv.setOnClickListener(this); checkPermission(); } private void initCameraGlView() { if (mHasPermission && mCameraGlView == null) { View view = ViewUtil.inflateViewById(this, R.layout.layout_camera_gl_view); mCameraLayout.addView(view); mCameraGlView = $(R.id.id_video_gl_view); int width = 1280;//ScreenUtils.getScreenWidth(this); int height = 720;//ScreenUtils.getScreenHeight(this); LogUtil.i(TAG, "width:" + width + ",height:" + height); mCameraGlView.setVideoSize(width, height); } } @Override public void onResume() { super.onResume(); LogUtil.i(TAG, "onResume:"); showPreview(); } private void showPreview() { if (mHasPermission && !mHasShow) { mCameraLayout.setVisibility(View.VISIBLE); initCameraGlView(); mCameraGlView.onResume(); mHasShow = true; } } @Override public void onPause() { LogUtil.i(TAG, "onPause:"); stopRecording(); if (mHasPermission && mHasShow) { mCameraGlView.onPause(); mHasShow = false; } super.onPause(); } @Override public void onClick(View v) { int id = v.getId(); switch (id) { case R.id.id_video_flash_iv: mCurFlashModeIndex = (mCurFlashModeIndex + 1) % FLASH_MODES.length; mCameraGlView.setFlashMode(FLASH_MODES[mCurFlashModeIndex]); mFlashIv.setImageResource(FLASH_MODE_IMGS[mCurFlashModeIndex]); break; case R.id.id_video_camera_iv: mCurCameraIdIndex = (mCurCameraIdIndex + 1) % CAMERA_IDS.length; mCameraGlView.setCameraId(CAMERA_IDS[mCurCameraIdIndex]); mCameraIv.setImageResource(CAMERA_ID_IMGS[mCurCameraIdIndex]); break; case R.id.id_video_drop_iv: revertInitView(); FileUtilsJ.delFile(mVideoPath); break; case R.id.id_video_select_iv: mIntent.putExtra(IntentConstants.FILE, mVideoPath); setResult(Activity.RESULT_OK, mIntent); onFinish(); break; case R.id.id_video_close_iv: onFinish(); break; } } @Override public void onFinish() { finish(); overridePendingTransition(0, R.anim.slide_to_bottom); } private void checkPermission() { if (PermissionModel.hasPermissions(this, mPermission)) { mHasPermission = true; showPreview(); } else { PermissionModel.requestPermissions(mPermission, PermissionModel.getRationalByPer(mPermission), new PermissionCallBack() { @Override public void onPermissionsAllGranted(int requestCode, @NonNull List<String> grantedPers) { mHasPermission = true; onResume(); } @Override public void onCancelPermissionRationale(int requestCode) { finish(); } @Override public void onPermissionsDenied(int requestCode, @NonNull List<String> deniedPers) { showPermissionSetting(); } }); } } private class RecordTouchListener implements View.OnTouchListener { @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); LogUtil.i(TAG, "action :" + action); switch (action) { case MotionEvent.ACTION_DOWN: if (!mIsRecording) { startRecording(); startRecordView(); } return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: stopRecording(); stopRecordView(); break; } return true; } } private String generalOutFile() { return StorageUtil.getFilesFolder() + System.currentTimeMillis() + ".mp4"; } private void revertInitView() { mFlashIv.setVisibility(View.VISIBLE); mCameraIv.setVisibility(View.VISIBLE); mRecordIv.setVisibility(View.VISIBLE); mProgressView.setVisibility(View.VISIBLE); mProgressView.clear(); mCloseIv.setVisibility(View.VISIBLE); mDropIv.setVisibility(View.GONE); mSelectIv.setVisibility(View.GONE); stopPlayVideo(); showPreview(); } private void startRecordView() { mFlashIv.setVisibility(View.GONE); mCameraIv.setVisibility(View.GONE); mCloseIv.setVisibility(View.GONE); mDropIv.setVisibility(View.GONE); mSelectIv.setVisibility(View.GONE); mProgressView.startAutoUpdate(); } private void stopRecordView() { mFlashIv.setVisibility(View.GONE); mCameraIv.setVisibility(View.GONE); mRecordIv.setVisibility(View.INVISIBLE); mProgressView.setVisibility(View.INVISIBLE); mCloseIv.setVisibility(View.INVISIBLE); mDropIv.setVisibility(View.VISIBLE); mSelectIv.setVisibility(View.VISIBLE); mProgressView.stopAutoUpdate(); mHasShow = false; if (mCameraGlView != null) { mCameraGlView.onPause(); mCameraLayout.setVisibility(View.INVISIBLE); mCameraLayout.removeAllViews(); mCameraGlView = null; } startPlayVideo(); } private void stopPlayVideo() { mVideoView.stopPlayback(); mVideoView.setVideoURI(null); mVideoView.setVisibility(View.GONE); } private void startPlayVideo() { mVideoView.setVisibility(View.VISIBLE); mHandler.postDelayed(new Runnable() { @Override public void run() { //delay for 800 ms if (FileUtilsJ.exist(mVideoPath)) { Uri uri = FileProvider.getUriForFile(VideoRecordActivity.this, GlobalParams.PROVIDER_AUTH, new File(mVideoPath)); LogUtil.i("MediaMuxerWrapper", "setVideoPath:" + mVideoPath); mVideoView.setVideoURI(uri); mVideoView.requestFocus(); mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { LogUtil.i("MediaMuxerWrapper", "video start"); mVideoView.start(); } }); mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { mVideoView.start(); } }); } else { VideoRecordActivity.this.revertInitView(); } } }, 300); } private void startRecording() { mIsRecording = true; try { mVideoPath = generalOutFile(); // if you record audio only, ".m4a" is also OK. mMuxer = new MediaMuxerWrapper(mVideoPath); // for video capturing new MediaVideoEncoder(mMuxer, mMediaEncoderListener, mCameraGlView.getVideoWidth(), mCameraGlView.getVideoHeight()); // for audio capturing new MediaAudioEncoder(mMuxer, mMediaEncoderListener); mMuxer.prepare(); mMuxer.startRecording(); } catch (final IOException e) { e.printStackTrace(); } } private void stopRecording() { mIsRecording = false; if (mMuxer != null) { mMuxer.stopRecording(); mMuxer = null; } } /** * callback methods from encoder */ private final MediaEncoder.MediaEncoderListener mMediaEncoderListener = new MediaEncoder.MediaEncoderListener() { @Override public void onPrepared(final MediaEncoder encoder) { LogUtil.i(TAG, "onPrepared:encoder=" + encoder); if (encoder instanceof MediaVideoEncoder) { mCameraGlView.setVideoEncoder((MediaVideoEncoder) encoder); } } @Override public void onStopped(final MediaEncoder encoder) { LogUtil.i(TAG, "onStopped:encoder=" + encoder); if (encoder instanceof MediaVideoEncoder) mCameraGlView.setVideoEncoder(null); } }; @Override public void onProgress(float progress) { //note:in thread LogUtil.i(TAG, "onProgress:" + progress); } @Override public void onProgressFinish() { //note:in thread LogUtil.i(TAG, "onProgressFinish"); mHandler.post(new Runnable() { @Override public void run() { mProgressView.stopAutoUpdate(); VideoRecordActivity.this.stopRecording(); VideoRecordActivity.this.stopRecordView(); } }); } }