https://blog.csdn.net/qq_38907791/article/details/87984378
源码
https://www.cnblogs.com/zhujiabin/p/4218209.htmls
//布局
<RelativeLayout
android:id="@+id/layout_gesture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#000"
android:gravity="center_horizontal">
<SurfaceView
android:id="@+id/record_surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<ImageView
android:id="@+id/changing"
android:background="@drawable/rotate"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_width="30dp"
android:layout_height="30dp" />
<ImageView
android:id="@+id/change"
android:background="@drawable/rotate"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:layout_width="30dp"
android:layout_height="30dp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#80ffffff"
android:padding="10dp">
<!-- 开始/结束 录制按钮 -->
<ImageView
android:id="@+id/record_control"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:onClick="startRecord"
android:src="@drawable/recordvideo_start" />
<ImageView
android:id="@+id/record_pause"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:onClick="stopRecord"
android:src="@drawable/control_pause"
android:visibility="gone" />
<Chronometer
android:id="@+id/record_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:format="%s" />
</RelativeLayout>
import android.Manifest;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import camera1video.android.example.com.android_camera1video_master.util.VideoUtils;
public class CustomRecordActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "CustomRecordActivity";
private Executor executor = Executors.newFixedThreadPool(1);
private ImageView mRecordControl;
private ImageView mPauseRecord;
private ImageView mChange;
private ImageView mChanging;
private SurfaceView surfaceView;
private SurfaceHolder mSurfaceHolder;
private Chronometer mRecordTime;
//录像机状态标识
private int mRecorderState;
public static final int STATE_INIT = 0;
public static final int STATE_RECORDING = 1;
public static final int STATE_PAUSE = 2;
public static final int CAMERA_OK = 1;
private long mPauseTime = 0; //录制暂停时间间隔
int cameraType = 0;
int cameraFlag = 1; //1为后置
int flashType;
// 存储文件
private Camera mCamera;
private MediaRecorder mediaRecorder;
private String currentVideoFilePath;
private String saveVideoPath = "";
private String str = null;
private MediaRecorder.OnErrorListener OnErrorListener = new MediaRecorder.OnErrorListener() {
@Override
public void onError(MediaRecorder mediaRecorder, int what, int extra) {
try {
if (mediaRecorder != null) {
mediaRecorder.reset();
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
if (Build.VERSION.SDK_INT > 22) {
if (ContextCompat.checkSelfPermission(CustomRecordActivity.this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
//先判断有没有权限 ,没有就在这里进行权限的申请
ActivityCompat.requestPermissions(CustomRecordActivity.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, CAMERA_OK);
initView();
} else {
//说明已经获取到摄像头权限了
Log.i("CustomRecordActivity", "已经获取了权限");
initView();
}
}
}
private void initView() {
surfaceView = (SurfaceView) findViewById(R.id.record_surfaceView);
mRecordControl = (ImageView) findViewById(R.id.record_control);
mRecordTime = (Chronometer) findViewById(R.id.record_time);
mPauseRecord = (ImageView) findViewById(R.id.record_pause);
mChange = (ImageView) findViewById(R.id.change);
mChanging = (ImageView) findViewById(R.id.changing);
mRecordControl.setOnClickListener(this);
mPauseRecord.setOnClickListener(this);
mChange.setOnClickListener(this);
mChanging.setOnClickListener(this);
mPauseRecord.setEnabled(false);
/*ViewGroup.LayoutParams lp = surfaceView.getLayoutParams();
lp.width = 720;
lp.height =1280;
surfaceView.setLayoutParams(lp);*/
//配置SurfaceHolder
mSurfaceHolder = surfaceView.getHolder();
// 设置Surface不需要维护自己的缓冲区
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// 设置分辨率
mSurfaceHolder.setFixedSize(720, 1280);
// 设置该组件不会让屏幕自动关闭
mSurfaceHolder.setKeepScreenOn(true);
//回调接口
mSurfaceHolder.addCallback(mSurfaceCallBack);
}
private SurfaceHolder.Callback mSurfaceCallBack = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
initCamera();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
if (mSurfaceHolder.getSurface() == null) {
return;
}
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
releaseCamera();
}
};
/**
* 设置摄像头为竖屏
*/
private void configCameraParams() {
Camera.Parameters params = mCamera.getParameters();
/* str = params.get("video-rotation-supported");
if (str != null ) {
if (str.equals("true")) {
Log.e("video-rotation-111","str支持旋转");
Show();
} else {
Log.e("video-rotation-333","str不支持旋转");
Show();
}
}else {
Log.e("video-rotation-222","不支持旋转");
NoShow();
}*/
params.setPreviewSize(720,1280);
//设置相机的横竖屏(竖屏需要旋转90°)
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
//params.set("orientation", "portrait");
params.set("video-rotation","90");
//设置预览图像的旋转方向video-rotation=90
//mCamera.setDisplayOrientation(0);
} else {
//params.set("orientation", "landscape");
params.set("video-rotation","0");
//设置预览图像的旋转方向
//mCamera.setDisplayOrientation(90);
}
//设置聚焦模式
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
//缩短Recording启动时间
params.setRecordingHint(true);
//影像稳定能力
if (params.isVideoStabilizationSupported())
params.setVideoStabilization(true);
mCamera.setParameters(params);
//mCamera.setDisplayOrientation(90);
}
private void Show() {
AlertDialog.Builder builder = new AlertDialog.Builder(this).setIcon(R.mipmap.ic_launcher).setTitle("支持旋转")
.setCancelable(false)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
builder.create().show();
}
private void NoShow() {
AlertDialog.Builder builder = new AlertDialog.Builder(this).setIcon(R.mipmap.ic_launcher).setTitle("不支持旋转")
.setCancelable(false)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
builder.create().show();
}
/**
* 释放摄像头资源
*/
private void releaseCamera() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
/**
* 开始录制视频
*/
public boolean startRecord() {
initCamera();
//录制视频前必须先解锁Camera
mCamera.unlock();
configMediaRecorder();
try {
//开始录制
mediaRecorder.prepare();
mediaRecorder.start();
} catch (IOException e) {
return false;
}
return true;
}
/**
* 停止录制视频
*/
public void stopRecord() {
// 设置后不会崩
mediaRecorder.setOnErrorListener(null);
mediaRecorder.setPreviewDisplay(null);
//停止录制
mediaRecorder.stop();
mediaRecorder.reset();
//释放资源
mediaRecorder.release();
mediaRecorder = null;
}
/**
* 合并录像视频方法
*/
private void mergeRecordVideoFile() {
new Thread(new Runnable() {
@Override
public void run() {
try {
String[] str = new String[]{saveVideoPath, currentVideoFilePath};
//将2个视频文件合并到 append.mp4文件下
VideoUtils.appendVideo(CustomRecordActivity.this, getVideoFilePath(CustomRecordActivity.this) + "append.mp4", str);
File reName = new File(saveVideoPath);
File f = new File(getVideoFilePath(CustomRecordActivity.this) + "append.mp4");
//再将合成的append.mp4视频文件 移动到 saveVideoPath 路径下
f.renameTo(reName);
if (reName.exists()) {
f.delete();
new File(currentVideoFilePath).delete();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 点击中间按钮,执行的UI更新操作
*/
private void refreshControlUI() {
if (mRecorderState == STATE_INIT) {
//录像时间计时
mRecordTime.setBase(SystemClock.elapsedRealtime());
mRecordTime.start();
mRecordControl.setImageResource(R.drawable.recordvideo_stop);
//1s后才能按停止录制按钮
mRecordControl.setEnabled(false);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mRecordControl.setEnabled(true);
}
}, 1000);
mPauseRecord.setVisibility(View.VISIBLE);
mPauseRecord.setEnabled(true);
} else if (mRecorderState == STATE_RECORDING) {
mPauseTime = 0;
mRecordTime.stop();
mRecordControl.setImageResource(R.drawable.recordvideo_start);
mPauseRecord.setVisibility(View.GONE);
mPauseRecord.setEnabled(false);
}
}
/**
* 点击暂停继续按钮,执行的UI更新操作
*/
private void refreshPauseUI() {
if (mRecorderState == STATE_RECORDING) {
mPauseRecord.setImageResource(R.drawable.control_play);
mPauseTime = SystemClock.elapsedRealtime();
mRecordTime.stop();
} else if (mRecorderState == STATE_PAUSE) {
mPauseRecord.setImageResource(R.drawable.control_pause);
if (mPauseTime == 0) {
mRecordTime.setBase(SystemClock.elapsedRealtime());
} else {
mRecordTime.setBase(SystemClock.elapsedRealtime() - (mPauseTime - mRecordTime.getBase()));
}
mRecordTime.start();
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.record_control: {
if (mRecorderState == STATE_INIT) {
if (getVideoFilePath(getApplicationContext()) == null)
return;
//视频文件保存路径,configMediaRecorder方法中会设置
currentVideoFilePath = getVideoFilePath(getApplicationContext()) + getVideoName();
//开始录制视频
if (!startRecord())
return;
refreshControlUI();
mRecorderState = STATE_RECORDING;
} else if (mRecorderState == STATE_RECORDING) {
//停止视频录制
stopRecord();
//先给Camera加锁后再释放相机
mCamera.lock();
releaseCamera();
refreshControlUI();
//判断是否进行视频合并
if ("".equals(saveVideoPath)) {
saveVideoPath = currentVideoFilePath;
} else {
mergeRecordVideoFile();
}
mRecorderState = STATE_INIT;
//延迟一秒跳转到播放器,(确保视频合并完成后跳转) TODO 具体的逻辑可根据自己的使用场景跳转
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(CustomRecordActivity.this, PlayVideoActivity.class);
Bundle bundle = new Bundle();
bundle.putString("videoPath", saveVideoPath);
intent.putExtras(bundle);
startActivity(intent);
finish();
}
}, 1000);
} else if (mRecorderState == STATE_PAUSE) {
//代表视频暂停录制时,点击中心按钮
Intent intent = new Intent(CustomRecordActivity.this, PlayVideoActivity.class);
Bundle bundle = new Bundle();
bundle.putString("videoPath", saveVideoPath);
intent.putExtras(bundle);
startActivity(intent);
finish();
}
break;
}
case R.id.record_pause: {
if (mRecorderState == STATE_RECORDING) {
//正在录制的视频,点击后暂停
//取消自动对焦
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success)
CustomRecordActivity.this.mCamera.cancelAutoFocus();
}
});
stopRecord();
refreshPauseUI();
//判断是否进行视频合并
if ("".equals(saveVideoPath)) {
saveVideoPath = currentVideoFilePath;
} else {
mergeRecordVideoFile();
}
mRecorderState = STATE_PAUSE;
} else if (mRecorderState == STATE_PAUSE) {
if (getVideoFilePath(getApplicationContext()) == null)
return;
//视频文件保存路径,configMediaRecorder方法中会设置
currentVideoFilePath = getVideoFilePath(getApplicationContext()) + getVideoName();
//继续视频录制
if (!startRecord()) {
return;
}
refreshPauseUI();
mRecorderState = STATE_RECORDING;
}
}
case R.id.change:
switchCamera();
break;
case R.id.changing:
// 一个自定义的布局,作为显示的内容
View contentView = LayoutInflater.from(this).inflate(
R.layout.popu, null);
final PopupWindow popupWindow = new PopupWindow(contentView,
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
contentView.findViewById(R.id.num1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
popupWindow.dismiss();
View content = LayoutInflater.from(CustomRecordActivity.this).inflate(
R.layout.popuwindow, null);
final PopupWindow popup = new PopupWindow(content,
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
content.findViewById(R.id.btn1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
popup.dismiss();
ViewGroup.LayoutParams lp = surfaceView.getLayoutParams();
lp.width = 120;
lp.height =160;
surfaceView.setLayoutParams(lp);
}
});
content.findViewById(R.id.btn2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
popup.dismiss();
ViewGroup.LayoutParams lp = surfaceView.getLayoutParams();
lp.width = 420;
lp.height =640;
surfaceView.setLayoutParams(lp);
}
});
content.findViewById(R.id.btn3).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
popup.dismiss();
ViewGroup.LayoutParams lp = surfaceView.getLayoutParams();
lp.width = 720;
lp.height =1280;
surfaceView.setLayoutParams(lp);
}
});
content.findViewById(R.id.btn4).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
popup.dismiss();
ViewGroup.LayoutParams lp = surfaceView.getLayoutParams();
lp.width = 1280;
lp.height =1920;
surfaceView.setLayoutParams(lp);
}
});
popup.setTouchable(true);
popup.setTouchInterceptor(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.i("mengdd", "onTouch : ");
return false;
// 这里如果返回true的话,touch事件将被拦截
// 拦截后 PopupWindow的onTouchEvent不被调用,这样点击外部区域无法dismiss
}
});
// 如果不设置PopupWindow的背景,无论是点击外部区域还是Back键都无法dismiss弹框
// 我觉得这里是API的一个bug
popup.setBackgroundDrawable(getResources().getDrawable(
R.drawable.ic_launcher_background));
// 设置好参数之后再show
popup.showAsDropDown(view);
}
});
contentView.findViewById(R.id.num2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(CustomRecordActivity.this,"旋转",Toast.LENGTH_SHORT);
Camera.Parameters params = mCamera.getParameters();
str = params.get("video-rotation-supported");
if (str != null ) {
if (str.equals("true")) {
Log.e("video-rotation-111","str支持旋转");
Show();
popupWindow.dismiss();
} else {
Log.e("video-rotation-333","str不支持旋转");
NoShow();
popupWindow.dismiss();
}
}else {
Log.e("video-rotation-222","不支持旋转");
NoShow();
popupWindow.dismiss();
}
params.setPreviewSize(720,1280);
//设置相机的横竖屏(竖屏需要旋转90°)
if (getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
//params.set("orientation", "portrait");
params.set("video-rotation","90");
//设置预览图像的旋转方向video-rotation=90
//mCamera.setDisplayOrientation(0);
} else {
//params.set("orientation", "landscape");
params.set("video-rotation","0");
//设置预览图像的旋转方向
//mCamera.setDisplayOrientation(90);
}
//设置聚焦模式
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
//缩短Recording启动时间
params.setRecordingHint(true);
//影像稳定能力
if (params.isVideoStabilizationSupported())
params.setVideoStabilization(true);
mCamera.setParameters(params);
//mCamera.setDisplayOrientation(90);
}
});
popupWindow.setTouchable(true);
popupWindow.setTouchInterceptor(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.i("mengdd", "onTouch : ");
return false;
// 这里如果返回true的话,touch事件将被拦截
// 拦截后 PopupWindow的onTouchEvent不被调用,这样点击外部区域无法dismiss
}
});
// 如果不设置PopupWindow的背景,无论是点击外部区域还是Back键都无法dismiss弹框
// 我觉得这里是API的一个bug
popupWindow.setBackgroundDrawable(getResources().getDrawable(
R.drawable.ic_launcher_background));
// 设置好参数之后再show
popupWindow.showAsDropDown(view);
break;
}
}
/**
* 初始化摄像头
*
* @throws IOException
*/
private void initCamera() {
if (mCamera != null) {
releaseCamera();
}
mCamera = Camera.open(0);
if (mCamera == null) {
Toast.makeText(this, "未能获取到相机!", Toast.LENGTH_SHORT).show();
return;
}
try {
//将相机与SurfaceHolder绑定
mCamera.setPreviewDisplay(mSurfaceHolder);
//配置CameraParams
configCameraParams();
//启动相机预览
mCamera.startPreview();
} catch (IOException e) {
//有的手机会因为兼容问题报错,这就需要开发者针对特定机型去做适配了
Log.e(TAG, "Error starting camera preview: " + e.getMessage());
}
}
/**
* 切换摄像头
*/
public void switchCamera() {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
int cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数0或者1;
try {
for (int i = 0; i < cameraCount; i++) {
Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息
if (cameraFlag == 1) {
//后置到前置
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置
//frontCameraRotate();//前置旋转摄像头度数
switchCameraLogic(i, 0, 90);
break;
}
} else {
//前置到后置
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置
switchCameraLogic(i, 1, 90);
break;
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
/***
* 处理摄像头切换逻辑
*
* @param i 哪一个,前置还是后置
* @param flag 切换后的标志
* @param orientation 旋转的角度
*/
private void switchCameraLogic(int i, int flag, int orientation) {
if (mCamera != null) {
mCamera.lock();
}
releaseCamera();
mCamera = Camera.open(i);//打开当前选中的摄像头
try {
mCamera.setDisplayOrientation(orientation);
mCamera.setPreviewDisplay(mSurfaceHolder);
} catch (IOException e) {
e.printStackTrace();
}
cameraFlag = flag;
FlashLogic(mCamera.getParameters(), 0, false);
mCamera.startPreview();
cameraType = i;
mCamera.unlock();
}
/**
* 闪光灯逻辑
*
* @param p 相机参数
* @param type 打开还是关闭
* @param isOn 是否启动
*/
private void FlashLogic(Camera.Parameters p, int type, boolean isOn) {
flashType = type;
if (type == 0) {
if (isOn) {
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(p);
}
} else {
if (isOn) {
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(p);
}
}
}
/**
* 配置MediaRecorder()
*/
private void configMediaRecorder() {
mediaRecorder = new MediaRecorder();
mediaRecorder.reset();
mediaRecorder.setCamera(mCamera);
mediaRecorder.setOnErrorListener(OnErrorListener);
//使用SurfaceView预览
mediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
//1.设置采集声音
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//设置采集图像
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
//2.设置视频,音频的输出格式 mp4
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
//3.设置音频的编码格式
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
//设置图像的编码格式
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
//音频一秒钟包含多少数据位
CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
mediaRecorder.setAudioEncodingBitRate(44100);
if (mProfile.videoBitRate > 2 * 1024 * 1024) {
mediaRecorder.setVideoEncodingBitRate(2 * 1024 * 1024);
Log.e("aaa","1024*1024");
}
else {
mediaRecorder.setVideoEncodingBitRate(1024 * 1024);
Log.e("bbb","1024*1024");
}
mediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);
//设置选择角度,顺时针方向,因为默认是逆向90度的,这样图像就是正常显示了,这里设置的是观看保存后的视频的角度
mediaRecorder.setOrientationHint(90);
//设置录像的分辨率
mediaRecorder.setVideoSize(720, 1280);
//设置录像视频输出地址
mediaRecorder.setOutputFile(currentVideoFilePath);
}
/**
* 创建视频文件保存路径
*/
private String getVideoFilePath(Context context) {
final File dir = context.getExternalFilesDir(null);
return (dir == null ? "" : (dir.getAbsolutePath() + "/"))
+ System.currentTimeMillis() + ".mp4";
}
public static String getSDPath(Context context) {
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
Toast.makeText(context, "请查看您的SD卡是否存在!", Toast.LENGTH_SHORT).show();
return null;
}
File sdDir = Environment.getExternalStorageDirectory();
File eis = new File(sdDir.toString() + "/RecordVideo/");
if (!eis.exists()) {
eis.mkdir();
}
return sdDir.toString() + "/RecordVideo/";
}
private String getVideoName() {
return "VID_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".mp4";
}
//activity监听屏幕旋转
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Nothing need to be done here
Log.e("TAG", "横屏");
Toast.makeText(this, "1", Toast.LENGTH_SHORT);
//处理代码
// 设置分辨率
ViewGroup.LayoutParams lp = surfaceView.getLayoutParams();
lp.width = 720;
lp.height =1280;
surfaceView.setLayoutParams(lp);
} else {
// Nothing need to be done here
Log.e("TAG", "竖屏");
Toast.makeText(this, "1", Toast.LENGTH_SHORT);
//处理代码
// 设置分辨率
ViewGroup.LayoutParams lp = surfaceView.getLayoutParams();
lp.width = 720;
lp.height =1280;
surfaceView.setLayoutParams(lp);
}
}
}
//权限
<uses-permission android:name="android.permission.FLASHLIGHT" />
<!--相机必须权限-->
<uses-permission android:name="android.permission.CAMERA" />
<!--相机录像权限-->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!--存储读写权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--如果需要用GPS位置信息标记图像,则必须请求设置此权限-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 下面这个特性声明针对Android 5(API级别21)或更高才需要添加-->
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.autofocus"/>
<SurfaceView
android:id="@+id/record_surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#80ffffff"
android:padding="10dp">
<!-- 开始/结束 录制按钮 -->
<ImageView
android:id="@+id/record_control"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:onClick="startRecord"
android:src="@drawable/recordvideo_start" />
<ImageView
android:id="@+id/record_pause"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:onClick="stopRecord"
android:src="@drawable/control_pause"
android:visibility="gone" />
<Chronometer
android:id="@+id/record_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:format="%s" />
</RelativeLayout>
control_pause.png
control_play.png
record_camera_switch_normal.png
recordvideo_start.png
recordvideo_stop.png
seek_bkg.png
seekbar_thumb_normal.png
seekbar_thumb_pressed.png
网友评论