拍照与录屏功能

实现录屏功能

调用

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "PlayActivity";
    private SurfaceView surfaceView;
    private CameraUtils cameraUtils;
    private String path, name;
    private ImageView btn;
    private ImageView camera;
    private ImageView change;
    int x = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        btn = (ImageView) findViewById(R.id.btn);
        camera = (ImageView) findViewById(R.id.camera);
        change = (ImageView) findViewById(R.id.change);
        surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        cameraUtils = new CameraUtils();
        cameraUtils.create(surfaceView, this);
        path = Environment.getExternalStorageDirectory() + "/" +
                DateFormat.format("yyyy-MM-dd_kk-mm-ss", new Date().getTime()) +
                ".mp4";;
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (x == 0) {
                    // cameraUtils.changeCamera();
                    cameraUtils.startRecord(path);
                    btn.setImageResource(R.drawable.video);
                    x = 1;
                } else if (x == 1) {
                    cameraUtils.stopRecord();
                    btn.setImageResource(R.drawable.video1);
                    x=0;
                }

            }
        });
        camera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                cameraUtils.takePicture(path, "name.png");


            }
        });

        change.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                cameraUtils.changeCamera();
            }
        });


    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: ");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause: ");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: ");
        cameraUtils.stop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
        cameraUtils.destroy();
    }
}

CameraUtils类


public class CameraUtils {
    private MediaRecorderBuilder mRecorder;
    private Camera camera;
    /*** 标识当前是前摄像头还是后摄像头  back:0  front:1*/
    private int backOrFtont = 1;
    private SurfaceHolder.Callback callback;
    private Context context;
    private SurfaceView surfaceView;
    /***录制视频的videoSize*/
    private int height = 720, width = 1280;

    public void create(SurfaceView surfaceView, Context context) {
        this.context = context;
        this.surfaceView = surfaceView;
        surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceView.setKeepScreenOn(true);
        callback = new SurfaceHolder.Callback() {
            public void surfaceCreated(SurfaceHolder holder) {
                camera = Camera.open();
                // getVideoSize();
                mRecorder = new MediaRecorderBuilder();
            }

            public void surfaceChanged(SurfaceHolder holder, int format,
                                       int width, int height) {
                doChange(holder);
                focus();
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                if (camera != null) {
                    camera.release();
                    camera = null;
                }
            }
        };
        surfaceView.getHolder().addCallback(callback);

    }

    private void doChange(SurfaceHolder holder) {
        try {
            camera.setPreviewDisplay(holder);
            camera.setDisplayOrientation(90);
            camera.startPreview();
            focus();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 切换摄像头
     */
    public void changeCamera() {
        int cameraCount = 0;
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        cameraCount = Camera.getNumberOfCameras();
        for (int i = 0; i < cameraCount; i++) {
            Camera.getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT && backOrFtont == 0) {
                camera.stopPreview();
                camera.release();
                camera = null;
                camera = Camera.open(i);
                try {
                    camera.setPreviewDisplay(surfaceView.getHolder());
                    camera.setDisplayOrientation(90);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                backOrFtont = 1;
                camera.startPreview();
                break;
            } else if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK && backOrFtont == 1) {
                camera.stopPreview();
                camera.release();
                camera = null;
                camera = Camera.open(i);
                try {
                    camera.setPreviewDisplay(surfaceView.getHolder());
                    camera.setDisplayOrientation(90);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                camera.startPreview();
                backOrFtont = 0;
                break;
            }
        }
        focus();

    }

    public void stopRecord() {
        try {
            mRecorder.stop();
            camera.release();
            camera = Camera.open();
            doChange(surfaceView.getHolder());
            Toast.makeText(context, "结束录制", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            Log.e("pan", "error:" + e);
        }

    }


    public void stop() {
        mRecorder.stop();
        camera.release();
    }

    public void destroy() {
        mRecorder.stop();
        mRecorder = null;
        if (camera != null) {
            camera.release();
            camera = null;
        }

    }

    /**
     * @param path 保存的路径
     */
    public void startRecord(String path) {
        try {
            camera.unlock();
            mRecorder.setCamera(camera)
                    .setPreviewDisplay(surfaceView.getHolder().getSurface())
                    .Build().start();
            Toast.makeText(context, "开始录制,视频路径为:" + path, Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            Log.e("pan", "error:" + e);
            Toast.makeText(context, "录制异常:", Toast.LENGTH_SHORT).show();
        }
    }

    public void takePicture(String photoPath, String photoName) {
        camera.takePicture(null, null, new PictureCallBack(photoPath, photoName));
        Toast.makeText(context, "照片路径为:" + photoPath + photoName, Toast.LENGTH_SHORT).show();
    }

    /**
     * 聚焦
     */
    public void focus() {
        try {
            Camera.Parameters parameters = camera.getParameters();
            //  parameters.setPictureSize(width, 480);
            Log.e("pan", "wh:" + width + " " + height);
            parameters.setPreviewSize(width, height);
            // parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//设置图片大小
            camera.setParameters(parameters);
//            camera.cancelAutoFocus();
            camera.setDisplayOrientation(0);
        } catch (Exception e) {
            Log.e("pan", "error:" + e);
        }
    }

    /*** 拍照功能*/
    private class PictureCallBack implements Camera.PictureCallback {
        /*** 照片保存的路径和名称*/
        private String path;
        private String name;

        public PictureCallBack(String path, String name) {
            this.path = path;
            this.name = name;
        }

        @Override
        public void onPictureTaken(byte[] bytes, Camera camera) {
            File file1 = new File(path);
            if (!file1.exists()) {
                file1.mkdirs();
            }
            File file = new File(path, name);
            if (file.exists()) {
                file.delete();
            }
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(file);
                try {
                    fos.write(bytes);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            camera.startPreview();
        }
    }
}


MediaRecorderBuilder类


public class MediaRecorderBuilder {
    private MediaRecorder mediarecorder;
    private Camera mCamera = null;
    private int mAudioSource = MediaRecorder.AudioSource.CAMCORDER;//defalut,camcorder,mic,voice_call,voice_communication,voice_downlink, voice_recognition,  voice_uplink;
    private int mVideoSource = MediaRecorder.VideoSource.CAMERA; //default,CAMERA
    private int mOutputFormat = MediaRecorder.OutputFormat.MPEG_4; //输出格式MP4 amr_nb,amr_wb,default,mpeg_4,raw_amr,three_gpp.
    private int mAudioEncoder = MediaRecorder.AudioEncoder.DEFAULT;//声音编码 default,AAC,AMR_NB,AMR_WB
    private int mVideoEncoder = MediaRecorder.VideoEncoder.H264;//视频编码  default,H263,H264,MPEG_4_SP
    private String mOutputFile = "/sdcard/myVideo.3gp";//视频位置
    private int mVideoSizeWidth = 640;
    private int mVideoSizeHeight = 480;
    private int mVideoEncodingBitRate = 10 * 1024 * 1024;//提高帧频率,录像模糊,花屏,绿屏可写上调试
    private Surface mPreviewDisplay = null;
    private int mVideoFrameRate = 24;//帧
    private CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
    private MediaRecorder.OnErrorListener errorListener = null;
    private MediaRecorder.OnInfoListener infoListener = null;
    private int mOrientationHint = 0;

    public MediaRecorderBuilder MediaRecorderBuild() {
        mediarecorder = new MediaRecorder();
        return this;
    }

    /**
     * 设置摄像头
     *
     * @param camera
     * @return
     */
    public MediaRecorderBuilder setCamera(Camera camera) {
        mCamera = camera;
        return this;
    }

    public MediaRecorderBuilder setOrientationHint(int o) {
        mOrientationHint = o;
        return this;
    }

    /**
     * 设置音频资源
     *
     * @param audioSource
     * @return
     */
    public MediaRecorderBuilder setAudioSource(int audioSource) {
        mAudioSource = audioSource;
        return this;
    }

    /**
     * 设置视频资源
     *
     * @param videoSource
     * @return
     */
    public MediaRecorderBuilder setVideoSource(int videoSource) {
        mVideoSource = videoSource;
        return this;
    }

    /**
     * 输出格式
     *
     * @param outputFormat
     * @return
     */
    public MediaRecorderBuilder setOutputFormat(int outputFormat) {
        mOutputFormat = outputFormat;
        return this;
    }

    /**
     * 设置音频编码
     *
     * @param audioEncoder
     * @return
     */
    public MediaRecorderBuilder setAudioEncoder(int audioEncoder) {
        mAudioEncoder = audioEncoder;
        return this;
    }

    /**
     * 设置视频编码
     *
     * @param videoEncoder
     * @return
     */
    public MediaRecorderBuilder setVideoEncoder(int videoEncoder) {
        mVideoEncoder = videoEncoder;
        return this;
    }

    /**
     * 设置输出文件路径与文件名
     *
     * @param path
     * @return
     */
    public MediaRecorderBuilder setOutputFile(String path, String name) {
        mOutputFile = path + name;
        return this;
    }

    /**
     * 设置视频分辨率
     *
     * @param w
     * @param h
     * @return
     */
    public MediaRecorderBuilder setVideoSize(int w, int h) {
        mVideoSizeWidth = w;
        mVideoSizeHeight = h;
        return this;
    }

    /**
     * 设置视频帧率
     *
     * @param rate
     * @return
     */
    public MediaRecorderBuilder setVideoFrameRate(int rate) {
        mVideoFrameRate = rate;
        return this;
    }

    /**
     * 提高帧频率
     *
     * @param rate
     * @return
     */
    public MediaRecorderBuilder setVideoEncodingBitRate(int rate) {
        mVideoEncodingBitRate = rate;
        return this;
    }

    /**
     * 设置视频预览
     *
     * @param sf
     * @return
     */
    public MediaRecorderBuilder setPreviewDisplay(Surface sf) {
        mPreviewDisplay = sf;
        return this;
    }

    public MediaRecorderBuilder setProfile(CamcorderProfile pf) {
        mProfile = pf;
        return this;
    }

    /**
     * 设置监听
     *
     * @param listener
     */
    public MediaRecorderBuilder setOnErrorListener(MediaRecorder.OnErrorListener listener) {
        errorListener = listener;
        return this;
    }

    /**
     * 设置监听
     *
     * @param listener
     */
    public MediaRecorderBuilder setInfoListener(MediaRecorder.OnInfoListener listener) {
        infoListener = listener;
        return this;
    }


    /**
     * build
     */
    public MediaRecorderBuilder Build() {
        if (mVideoSource == MediaRecorder.VideoSource.CAMERA) {
            mediarecorder.setCamera(mCamera);//设置调用的摄像头
        }
        mediarecorder.setAudioSource(mAudioSource); //指定Audio,video来源
        mediarecorder.setVideoSource(mVideoSource);
        // 指定CamcorderProfile(需要API Level 8以上版本)
        mediarecorder.setProfile(mProfile);
        //使用CamcorderProfile做配置的话,输出格式,音频编码,视频编码 不要写
        // 设置输出格式和编码格式(针对低于API Level 8版本)
        mediarecorder.setOutputFormat(mOutputFormat); //设置输出格式,.THREE_GPP为3gp,.MPEG_4为mp4
        mediarecorder.setAudioEncoder(mAudioEncoder);//设置声音编码类型 mic
        mediarecorder.setVideoEncoder(mVideoEncoder);//设置视频编码类型,一般h263,h264
        mediarecorder.setOutputFile(mOutputFile);
        mediarecorder.setVideoSize(mVideoSizeWidth, mVideoSizeHeight);//设置视频分辨率,设置错误调用start()时会报错,可注释掉在运行程序测试,有时注释掉可以运行
        mediarecorder.setVideoFrameRate(mVideoFrameRate);//设置视频帧率,可省略
        mediarecorder.setVideoEncodingBitRate(mVideoEncodingBitRate);//提高帧频率,录像模糊,花屏,绿屏可写上调试
        mediarecorder.setPreviewDisplay(mPreviewDisplay); //设置视频预览
        if (errorListener != null) mediarecorder.setOnErrorListener(errorListener);
        if (infoListener != null) mediarecorder.setOnInfoListener(infoListener);
        mediarecorder.setOrientationHint(mOrientationHint);
        return this;
    }

    /**
     * 开始录制
     */
    public void start() throws IOException {
        mediarecorder.prepare();
        mediarecorder.start();
    }

    /**
     * 停止录制
     */
    public void stop() {
        mediarecorder.stop();// 停止录制
        mediarecorder.reset(); // 在重置mediarecorder
        mediarecorder.release();// 释放资源
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    X先生_未知数的X阅读 15,967评论 3 119
  • 下午开始看断舍离。 所谓“断舍离”,就是将我们不需要的、不合适的、不舒服的、换成我们需要的、合适且舒服的。 那具体...
    做大王好多年阅读 306评论 0 0
  • 充实忙碌的一夜,忙碌使人宁静,顾客的开心,才是我们最大的幸福
    乾立风中阅读 124评论 0 1
  • 一、前代猿猴形象分析 (一)先秦猿猴形象 先秦关于猿猴的记载并不多,而且还存在着部分如《山海经》中所涉及的“类猿物...
    Emrysyrm3阅读 9,957评论 5 17
  • 每个女孩都是人间天使,尽管个性不同,却都有自己最可爱的模样,这些年我爱过的女孩,在我心中每一个都是人间精品...
    曾小一阅读 895评论 12 43