ListerCi 2017-06-02 07:12 采纳率: 60%
浏览 4232
已结题

Android拍视频预览的界面被拉伸

最近 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" />

求大神解答

  • 写回答

2条回答 默认 最新

  • Tauren2614 2017-06-02 07:41
    关注

    预览尺寸设置不当会导致Camera预览变形

    http://www.xuebuyuan.com/1052006.html

    评论

报告相同问题?

悬赏问题

  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败
  • ¥15 MapReduce实现倒排索引失败
  • ¥15 ZABBIX6.0L连接数据库报错,如何解决?(操作系统-centos)
  • ¥15 找一位技术过硬的游戏pj程序员
  • ¥15 matlab生成电测深三层曲线模型代码
  • ¥50 随机森林与房贷信用风险模型