Camera1

Camera mCameraDevice = Camera.open(0);
Camera.Parameters mParameters = mCameraDevice.getParameters();
mParameters.set("video-rotation=90");
mCameraDevice.setParameters(mParameters); 
//布局
<SurfaceView
        android:id="@+id/capture_surfaceview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <Chronometer
        android:id="@+id/crm_count_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_margin="10.0dip"
        android:textSize="15.0sp" />
    <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/ib_stop"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_centerInParent="true"
            android:src="@drawable/recordvideo_start" />
        <ImageView
            android:id="@+id/ib_start"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerVertical="true"
            android:src="@drawable/control_pause"
            android:visibility="gone" />
    </RelativeLayout>
import android.Manifest;
import android.content.Context;
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.AppCompatActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.LinearLayout;
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 SurfaceView surfaceView;
    private SurfaceHolder mSurfaceHolder;
    private Chronometer mRecordTime;

    //DATA

    //录像机状态标识
    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 boolean isRecording;// 标记,判断当前是否正在录制
//    private boolean isPause; //暂停标识
    private long mPauseTime = 0;           //录制暂停时间间隔

    // 存储文件
    private File mVecordFile;
    private Camera mCamera;
    private MediaRecorder mediaRecorder;
    private String currentVideoFilePath;
    private String saveVideoPath = "";


    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);
        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);
        mRecordControl.setOnClickListener(this);
        mPauseRecord.setOnClickListener(this);
        mChange.setOnClickListener(this);
        mPauseRecord.setEnabled(false);

        /*LinearLayout.LayoutParams linear = (LinearLayout.LayoutParams) surfaceView.getLayoutParams();
        linear.weight = 1280;
        linear.height = 720;
        surfaceView.setLayoutParams(linear);*/

        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);
            } else {
                //说明已经获取到摄像头权限了
                Log.i("CustomRecordActivity", "已经获取了权限");
            }
        }

        //配置SurfaceHolder
        mSurfaceHolder = surfaceView.getHolder();
        // 设置Surface不需要维护自己的缓冲区
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        // 设置分辨率
        mSurfaceHolder.setFixedSize(320, 280);
        // 设置该组件不会让屏幕自动关闭
        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();
        }
    };


    /**
     * 初始化摄像头
     * @throws IOException
     */
    private void initCamera() {
        if (mCamera != null) {
            releaseCamera();
        }
        try {
            mCamera = Camera.open(0);
        }catch (Exception e) {
            Log.d("相机异常",mCamera+"   0");
        }

        Log.d("CustomRecordActivity",mCamera+"   0");

        if (mCamera == null) {
            Toast.makeText(this, "未能获取到相机!", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            //将相机与SurfaceHolder绑定
            mCamera.setPreviewDisplay(mSurfaceHolder);
            //配置CameraParams
            configCameraParams();
            //启动相机预览
            mCamera.startPreview();

            Log.d("CustomRecordActivity",mCamera+"   1");

        } catch (IOException e) {
            //有的手机会因为兼容问题报错,这就需要开发者针对特定机型去做适配了
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }


    /**
     * 设置摄像头为竖屏
     */
    private void configCameraParams() {
        Camera.Parameters params = mCamera.getParameters();
        //设置相机的横竖屏(竖屏需要旋转90°)
        if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
            params.set("orientation", "portrait");
            mCamera.setDisplayOrientation(90);
        } else {
            params.set("orientation", "landscape");
            mCamera.setDisplayOrientation(0);
        }
        //设置聚焦模式
        params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
        //缩短Recording启动时间
        params.setRecordingHint(true);
        //影像稳定能力
        if (params.isVideoStabilizationSupported())
            params.setVideoStabilization(true);
        mCamera.setParameters(params);
    }


    /**
     * 释放摄像头资源
     */
    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, getSDPath(CustomRecordActivity.this) + "append.mp4", str);
                    File reName = new File(saveVideoPath);
                    File f = new File(getSDPath(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);

            Log.d("CustomRecordActivity",mRecordTime+"   0");
        } else if (mRecorderState == STATE_RECORDING) {
            mPauseTime = 0;
            mRecordTime.stop();
            mRecordControl.setImageResource(R.drawable.recordvideo_start);
            mPauseRecord.setVisibility(View.GONE);
            mPauseRecord.setEnabled(false);

            Log.d("CustomRecordActivity",mRecordTime+"   0");
        }
    }

    /**
     * 点击暂停继续按钮,执行的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 (getSDPath(getApplicationContext()) == null)
                        return;
                    //视频文件保存路径,configMediaRecorder方法中会设置
                    currentVideoFilePath = getSDPath(getApplicationContext()) + getVideoName();
                    //开始录制视频
                    if (!startRecord())
                        return;
                    refreshControlUI();
                    mRecorderState = STATE_RECORDING;
                    Log.d("TAG","失败1");
                } 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);
                    Log.d("TAG","失败2");
                } 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();
                    Log.d("TAG","失败3");
                }
                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 (getSDPath(getApplicationContext()) == null)
                        return;

                    //视频文件保存路径,configMediaRecorder方法中会设置
                    currentVideoFilePath = getSDPath(getApplicationContext()) + getVideoName();

                    //继续视频录制
                    if (!startRecord()) {
                        return;
                    }
                    refreshPauseUI();

                    mRecorderState = STATE_RECORDING;
                }
            }
            case R.id.change:
                Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
                int cameras = Camera.getNumberOfCameras();
                for (int i = 0; i < cameras; i++) {
                    Camera.getCameraInfo(i,cameraInfo);
                    if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                        initCamera();
                    }
                }
                break;
        }

    }

    /**
     * 配置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);
        else
            mediaRecorder.setVideoEncodingBitRate(1024 * 1024);
        mediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);

        //设置选择角度,顺时针方向,因为默认是逆向90度的,这样图像就是正常显示了,这里设置的是观看保存后的视频的角度
        mediaRecorder.setOrientationHint(90);
        //设置录像的分辨率
        mediaRecorder.setVideoSize(352, 288);

        //设置录像视频输出地址
        mediaRecorder.setOutputFile(currentVideoFilePath);
    }

    /**
     * 创建视频文件保存路径
     */
    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.i("TAG","横屏");
            Toast.makeText(this,"1",Toast.LENGTH_SHORT);
            //处理代码
        } else {
            // Nothing need to be done here
            Log.i("TAG","竖屏");
            Toast.makeText(this,"1",Toast.LENGTH_SHORT);
            //处理代码
        }

    }
}
//权限
<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>
15042138-01e4aef07a3165b1.png
control_pause.png
15042138-fc791a067535bf3b.png
control_play.png
15042138-b03c900bf91c288d.png
record_camera_switch_normal.png
15042138-b1d9a7cc7a5d7513.png
recordvideo_start.png
15042138-96b1b026309d59c1.png
recordvideo_stop.png
15042138-eea71079190d85ef.png
seek_bkg.png
15042138-f78f3c91c4c3c6c5.png
seekbar_thumb_normal.png
15042138-12c8342379360e7e.png
seekbar_thumb_pressed.png

转载于:https://www.jianshu.com/p/6d1391fe81bb

猜你喜欢

转载自blog.csdn.net/weixin_33743703/article/details/91062318