最近 Android 需要做一个拍视频保存然后上传的功能,基本功能实现了,但是有一个小 bug,就是预览的时候界面明显被拉长了,但是各种预览设置的参数也都试过了,都没有用,来请教一下。
#代码如下:
##1. Activity
public class RecordActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private Button btnStartStop;
private boolean isRecording = false; // 标记是否已经在录制
private MediaRecorder mRecorder; // 音视频录制类
private Camera mCamera = null; // 相机
private List<Camera.Size> mSupportedPreviewSizes = null;
private Camera.Size mPreviewSize;
private Camera.Size mSize = null;// 相机的尺寸
private int mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK; // 默认后置摄像头
private static final SparseIntArray orientations = new SparseIntArray(); // 手机旋转对应的调整角度
static {
orientations.append(Surface.ROTATION_0, 90);
orientations.append(Surface.ROTATION_90, 0);
orientations.append(Surface.ROTATION_180, 270);
orientations.append(Surface.ROTATION_270, 180);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initWindow();
setContentView(R.layout.activity_record);
initViews();
}
/**
* 初始化窗口
*/
private void initWindow() {
requestWindowFeature(Window.FEATURE_NO_TITLE); // 去掉标题栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); // 设置全屏
// 设置竖屏显示
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// 选择支持半透明模式,在有 surfaceView 的 activity 中使用。
getWindow().setFormat(PixelFormat.TRANSLUCENT);
}
/**
* 视图对象初始化
*/
private void initViews() {
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview);
btnStartStop = (Button) findViewById(R.id.btnStartStop);
btnStartStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isRecording) {
startRecord();
} else {
stopRecord();
}
}
});
SurfaceHolder holder = mSurfaceView.getHolder(); // 取得holder
holder.setFormat(PixelFormat.TRANSPARENT);
holder.setKeepScreenOn(true);
holder.addCallback(this); // holder加入回调接口
}
/**
* 初始化相机
*/
private void initCamera() {
/**
* 默认打开后置摄像头
*/
if (Camera.getNumberOfCameras() == 2) {
mCamera = Camera.open(mCameraFacing);
} else {
mCamera = Camera.open();
}
CameraSizeComparator sizeComparator = new CameraSizeComparator();
Camera.Parameters parameters = mCamera.getParameters();
if (mSize == null) {
mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
Collections.sort(mSupportedPreviewSizes, sizeComparator);
for (int num = 0; num < mSupportedPreviewSizes.size(); num++) {
Camera.Size size = mSupportedPreviewSizes.get(num);
if (size.width >= 1000 && size.height >= 1000) {
this.mSize = size;
break;
}
}
mSize = mSupportedPreviewSizes.get(0);
/**
* 增加对聚焦模式的判断
*/
List<String> focusModesList = parameters.getSupportedFocusModes();
if (focusModesList.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
} else if (focusModesList.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
mCamera.setParameters(parameters);
}
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int orientation = orientations.get(rotation);
mCamera.setDisplayOrientation(orientation);
}
@Override
protected void onResume() {
super.onResume();
initCamera();
}
@Override
public void onPause() {
releaseCamera();
super.onPause();
}
/**
* 开始录制
*/
private void startRecord() {
if (mRecorder == null) {
mRecorder = new MediaRecorder(); // 创建MediaRecorder
}
if (mCamera != null) {
mCamera.stopPreview();
mCamera.unlock();
mRecorder.setCamera(mCamera);
}
try {
// 设置音频采集方式
mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
// 设置视频的采集方式
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
/*
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 设置文件的输出格式
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 设置audio的编码格式
mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置video的编码格式
mRecorder.setVideoEncodingBitRate(10 * 1024 * 1024); // 设置录制的视频编码比特率
mRecorder.setVideoFrameRate(30); // 设置录制的视频帧率
mRecorder.setVideoSize(1920, 1080); // 设置相机分辨率
*/
// 设置要捕获的视频的宽度和高度
// mSurfaceHolder.setFixedSize(optimalSize.width, optimalSize.height);
mRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
// 设置记录会话的最大持续时间(毫秒)
mRecorder.setMaxDuration(180 * 1000);
mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
/**
* 获取外部路径,然后将视频保存进去
*/
String path = Environment.getExternalStorageDirectory().getPath();
if (path != null) {
File dir = new File(path + "/crafts_videos");
if (!dir.exists()) {
dir.mkdir();
}
/**
* 将 currentTimeMillis() 作为文件名
*/
path = dir + "/" + System.currentTimeMillis() + ".mp4";
mRecorder.setOutputFile(path); //设置输出文件的路径
mRecorder.prepare(); //准备录制
mRecorder.start(); //开始录制
isRecording = true;
btnStartStop.setText("停止");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 停止录制
*/
private void stopRecord() {
try {
mRecorder.stop(); // 停止录制
mRecorder.reset(); // 重置
btnStartStop.setText("开始");
} catch (Exception e) {
e.printStackTrace();
}
isRecording = false;
}
/**
* 释放 MediaRecorder
*/
private void releaseMediaRecorder() {
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
}
/**
* 释放相机资源
*/
private void releaseCamera() {
try {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.unlock();
mCamera.release();
}
} catch (RuntimeException e) {
} finally {
mCamera = null;
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// 将holder,这个holder为开始在onCreate里面取得的holder,将它赋给mSurfaceHolder
mSurfaceHolder = holder;
if (mCamera == null) {
return;
}
try {
//设置显示
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (Exception e) {
e.printStackTrace();
releaseCamera();
finish();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// 将holder,这个holder为开始在onCreate里面取得的holder,将它赋给mSurfaceHolder
mSurfaceHolder = holder;
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// surfaceDestroyed的时候同时对象设置为null
if (isRecording && mCamera != null) {
mCamera.lock();
}
mSurfaceView = null;
mSurfaceHolder = null;
releaseMediaRecorder();
releaseCamera();
}
private class CameraSizeComparator implements Comparator<Camera.Size> {
public int compare(Camera.Size lhs, Camera.Size rhs) {
if (lhs.width == rhs.width) {
return 0;
} else if (lhs.width > rhs.width) {
return 1;
} else {
return -1;
}
}
}
}
##2. 布局
<?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"
android:orientation="vertical">
<SurfaceView
android:id="@+id/surfaceview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="@+id/btnStartStop"
android:layout_width="60dp"
android:layout_height="40dip"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:text="开始" />
</RelativeLayout>
##3. 权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
求大神解答