首页 > 学院 > 开发设计 > 正文

没加前后摄像头切换功能的视频录制功能

2019-11-06 09:55:46
字体:
来源:转载
供稿:网友

这个是视频录制和拍照功能合到一个页面的初期版本,有助于更好地理解视频录制功能,但可能有预览黑屏和画面反转的问题;

TakePicActivity.java:

package com.haier.uhome.appliance.newVersion.module.messageboard;import android.animation.Animator;import android.animation.ObjectAnimator;import android.app.Activity;import android.content.Intent;import android.graphics.PixelFormat;import android.hardware.Camera;import android.media.MediaRecorder;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.KeyEvent;import android.view.MotionEvent;import android.view.Surface;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.ViewGroup;import android.view.ViewTreeObserver;import android.view.animation.LinearInterpolator;import android.widget.Button;import android.widget.FrameLayout;import android.widget.ImageView;import android.widget.RelativeLayout;import android.widget.TextView;import android.widget.Toast;import com.haier.uhome.appliance.R;import com.haier.uhome.appliance.newVersion.module.messageboard.view.CirclePRogressView;import com.haier.uhome.common.util.LogUtil;import java.io.File;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Iterator;import java.util.List;import butterknife.BindView;import butterknife.ButterKnife;import butterknife.OnClick;public class TakePicActivity extends AppCompatActivity {    private static final String TAG = "TakePicActivity";    SurfaceView surfaceView;    SurfaceHolder surfaceHolder;    RelativeLayout rl_btn;    @BindView(R.id.fl_content)    FrameLayout flContent;    //进度条    @BindView(R.id.circleProgress)    CircleProgressView circleProgress;    @BindView(R.id.iv_turn)    ImageView ivTurn;    private Camera camera;    private Camera.Parameters parameters = null;    Bundle bundle = null; // 声明一个Bundle对象,用来存储数据    Button takepicture;    RelativeLayout rl_playPic;    int w, h;    protected boolean isPreview;    private MediaRecorder mMediaRecorder;    private boolean isRecording = true; // true表示没有录像,点击开始;false表示正在录像,点击暂停    private File mRecVedioPath;    private File mRecAudioFile;    //录制视频时的计时器    private TextView timer;    private int hour = 0;    private int minute = 0;    private int second = 0;    private boolean bool;    private Animator animator;    private boolean isRecordState = false;//是否是视频录制状态    private int progress;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_take_pic);        ButterKnife.bind(this);        takepicture = (Button) findViewById(R.id.takepicture);        surfaceView = (SurfaceView) this                .findViewById(R.id.surfaceView);        rl_btn = (RelativeLayout) this.findViewById(R.id.buttonLayout);        timer = (TextView) this.findViewById(R.id.show_time);        // 设置计时器不可见//        timer.setVisibility(View.GONE);        // 设置缓存路径        mRecVedioPath = new File(Environment.getExternalStorageDirectory()                .getAbsolutePath() + "/hfdatabase/video/temp/");        if (!mRecVedioPath.exists()) {            mRecVedioPath.mkdirs();        }        //圆形进度条设置        circleProgress.setBgColor(getResources().getColor(R.color.text_white));        circleProgress.setProgressColor(getResources().getColor(R.color.colorPrimaryDark));        ViewTreeObserver observerCircle = circleProgress.getViewTreeObserver();        observerCircle.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {            @Override            public boolean onPreDraw() {                progress = circleProgress.getmProgress();                return true;            }        });        surfaceView.getHolder()                .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        surfaceView.getHolder().setFixedSize(176, 144); //设置Surface分辨率        surfaceView.getHolder().setKeepScreenOn(true);// 屏幕常亮        surfaceView.getHolder().addCallback(new SurfaceCallback());//为SurfaceView的句柄添加一个回调函数        //长按录制        takepicture.setOnLongClickListener(new View.OnLongClickListener() {            @Override            public boolean onLongClick(View v) {                isRecordState = true;                if (isRecording) {                    /*                     * 点击开始录像                     */                    if (isPreview) {                        camera.stopPreview();                        camera.release();                        camera = null;                    }                    second = 0;                    minute = 0;                    hour = 0;                    bool = true;                    if (mMediaRecorder == null)                        mMediaRecorder = new MediaRecorder();                    else                        mMediaRecorder.reset();                    //拍摄视频时的相机配置                    if (camera != null) {                        freeCameraResource();                    }                    camera = Camera.open();                    camera.setDisplayOrientation(90);                    camera.startPreview();                    camera.unlock();                    mMediaRecorder.setCamera(camera);                    mMediaRecorder.setOnErrorListener(null);                    mMediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());                    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);                    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);                    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);                    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);                    mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);                    mMediaRecorder.setMaxDuration(60 * 1000);                    mMediaRecorder.setVideoSize(320, 240);                    mMediaRecorder.setVideoEncodingBitRate(1 * 1024 * 1024);// 设置帧频率,然后就清晰了//                    mMediaRecorder.setVideoFrameRate(15);                    mMediaRecorder.setOrientationHint(getPreviewDegree(TakePicActivity.this));// 输出旋转90度,保持竖屏录制                    try {                        mRecAudioFile = File.createTempFile("Vedio", ".mp4", mRecVedioPath);                    } catch (IOException e) {                        e.printStackTrace();                    }                    mMediaRecorder.setOutputFile(mRecAudioFile.getAbsolutePath());                    try {                        mMediaRecorder.prepare();                        timer.setVisibility(View.VISIBLE);                        handler.postDelayed(task, 1000);                        mMediaRecorder.start();                    } catch (Exception e) {                        e.printStackTrace();                    }                    showMsg("开始录制");//                    scalePic.setBackgroundDrawable(iconStop);                    isRecording = !isRecording;                    recordAnimater();                }                return false;            }        });        takepicture.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                switch (event.getAction()){                    case MotionEvent.ACTION_UP:                        Log.d(TAG, "onTouch: takepicture==setOnTouchListener==ACTION_UP");                        if(isRecordState){                            if(second < 1){//                                showMsg("录制时间太短");                                Toast.makeText(TakePicActivity.this, "录制时间太短", Toast.LENGTH_SHORT).show();//                                animator.cancel();                                try {                                    Thread.sleep(1000);                                } catch (InterruptedException e) {                                    e.printStackTrace();                                }                                if(animator.isRunning()){                                    animator.end();                                }//                                mMediaRecorder.setOnErrorListener(null);//                                mMediaRecorder.setPreviewDisplay(null);//                                mMediaRecorder.stop();//                                mMediaRecorder.reset();                            }else{                                if(animator.isRunning()){                                    animator.end();                                }                            }                        }                        break;                }                return false;            }        });    }    protected void onResume() {        super.onResume();        timer.setVisibility(View.GONE);        circleProgress.setVisibility(View.GONE);        isRecordState = false;    }    /*    * 视频录制时的进度条动画    * */    public void recordAnimater() {        //设置进度条        startAnimator();        animator.addListener(new Animator.AnimatorListener() {            @Override            public void onAnimationStart(Animator animation) {            }            @Override            public void onAnimationEnd(Animator animation) {                Log.i("animator", "stop");                /*                     * 点击停止                     */                try {                    bool = false;//                    isRecordState = false;                    mMediaRecorder.stop();                    timer.setText(format(hour) + ":" + format(minute) + ":" + format(second));                    mMediaRecorder.release();                    mMediaRecorder = null;                    //录制完成后播放摄像头                    freeCameraResource();                    videoRename();                } catch (Exception e) {                    e.printStackTrace();                }                isRecording = !isRecording;//                    scalePic.setBackgroundDrawable(iconStart);                showMsg("录制完成,已保存");//                        Intent backIntent = new Intent();//                        backIntent.putExtra("path", mrv_wx.mVecordFile.getAbsoluteFile().toString());//                        setResult(RESULT_OK, backIntent);//                        finish();                Intent displayIntent = new Intent(TakePicActivity.this, ShowPicActivity.class);                bundle = new Bundle();                bundle.putBoolean("isRecord", isRecordState);                bundle.putString("video_path", out.getAbsolutePath());                displayIntent.putExtras(bundle);                startActivity(displayIntent);            }            @Override            public void onAnimationCancel(Animator animation) {            }            @Override            public void onAnimationRepeat(Animator animation) {            }        });    }    @OnClick(R.id.iv_turn)    public void onClick() {    }    private final class SurfaceCallback implements SurfaceHolder.Callback {        @Override        public void surfaceCreated(SurfaceHolder holder) {            try {                if (camera != null) {                    freeCameraResource();                }                camera = Camera.open(); // 打开摄像头                parameters = camera.getParameters();                //加这句小米手机会黑屏//                parameters.setPreviewFrameRate(5); // 每秒5帧                parameters.setPictureFormat(PixelFormat.JPEG);// 设置照片的输出格式                parameters.set("jpeg-quality", 85);// 照片质量                int PreviewWidth = 0;                int PreviewHeight = 0;                // 选择合适的预览尺寸                List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();                // 如果sizeList只有一个我们也没有必要做什么了,因为就他一个别无选择                if (sizeList.size() > 1) {                    Iterator<Camera.Size> itor = sizeList.iterator();                    while (itor.hasNext()) {                        Camera.Size cur = itor.next();                        if (cur.width >= PreviewWidth                                && cur.height >= PreviewHeight) {                            PreviewWidth = cur.width;                            PreviewHeight = cur.height;                            break;                        }                    }                }                parameters.setPreviewSize(PreviewWidth, PreviewHeight); // 获得摄像区域的大小                parameters.setPictureSize(PreviewWidth, PreviewHeight); // 获得保存图片的大小//                parameters.setPreviewSize(320, 240); // 设置预览大小//                parameters.setPictureSize(320,240);//                    parameters.set("orientation", "portrait");                camera.setParameters(parameters);                camera.setPreviewDisplay(holder); // 设置用于显示拍照影像的SurfaceHolder对象                camera.setDisplayOrientation(getPreviewDegree(TakePicActivity.this));                camera.startPreview(); // 开始预览                isPreview = true;//                camera.autoFocus(null);            } catch (Exception e) {                e.printStackTrace();            }            surfaceHolder = holder;        }        @Override        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {            surfaceHolder = holder;            LogUtil.d(TAG,"surfaceChanged======");            camera.autoFocus(new Camera.AutoFocusCallback() {                @Override                public void onAutoFocus(boolean success, Camera camera) {//                    camera.setOneShotPreviewCallback(null);                    initCamera(width, height);                    camera.cancelAutoFocus();//只有加上了这一句,才会自动对焦。                }            });        }        @Override        public void surfaceDestroyed(SurfaceHolder holder) {            if (camera != null) {                if (isPreview) {                    camera.stopPreview();                    isPreview = false;                }                camera.release(); // 释放照相机                camera = null;            }            surfaceHolder = null;            surfaceView = null;            mMediaRecorder = null;        }    }    // 提供一个静态方法,用于根据手机方向获得相机预览画面旋转的角度    public static int getPreviewDegree(Activity activity) {        // 获得手机的方向        int rotation = activity.getWindowManager().getDefaultDisplay()                .getRotation();        int degree = 0;        // 根据手机的方向计算相机预览画面应该选择的角度        switch (rotation) {            case Surface.ROTATION_0:                degree = 90;                break;            case Surface.ROTATION_90:                degree = 0;                break;            case Surface.ROTATION_180:                degree = 270;                break;            case Surface.ROTATION_270:                degree = 180;                break;        }        return degree;    }    /**     * 按钮被点击触发的事件     *     * @param v     */    public void btnOnclick(View v) {        if (camera != null) {            switch (v.getId()) {                case R.id.takepicture:                    // 拍照                    camera.takePicture(null, null, new MyPictureCallback());                    break;            }        }    }    byte[] picData;    private final class MyPictureCallback implements Camera.PictureCallback {        @Override        public void onPictureTaken(byte[] data, Camera camera) {            try {                bundle = new Bundle();                bundle.putByteArray("bytes", data);//将图片字节数据保存在bundle中,实现数据交换                picData = data;//                saveToSDCard(data);//                camera.startPreview();//拍完照后,重新开始预览                if (bundle == null) {                    Toast.makeText(getapplicationContext(), "请先拍照",                            Toast.LENGTH_SHORT).show();                } else {                    Intent intent = new Intent();                    intent.setClass(getApplicationContext(), ShowPicActivity.class);                    bundle.putBoolean("isRecord", isRecordState);                    intent.putExtras(bundle);                    startActivity(intent);                }            } catch (Exception e) {                e.printStackTrace();            }        }    }    public void initCamera(int width, int height) {        parameters = camera.getParameters(); // 获取各项参数        parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式        parameters.setPreviewSize(width, height); // 设置预览大小//        List<Camera.Size> sizes =parameters.getSupportedPreviewSizes();//        Camera.Size optimalSize = getOptimalPreviewSize(sizes, 320,240);//        parameters.setPreviewSize(optimalSize.width, optimalSize.height);        parameters.setPreviewFrameRate(5);  //设置每秒显示4帧        parameters.setPictureSize(width, height); // 设置保存的图片尺寸        parameters.setJpegQuality(80); // 设置照片质量        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//1连续对焦        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);        camera.startPreview();        camera.cancelAutoFocus();// 2如果要实现连续的自动对焦,这一句必须加上    }    public boolean onTouchEvent(MotionEvent event) {        if (event.getAction() == KeyEvent.ACTION_DOWN) {            if (!isRecordState) {                camera.autoFocus(new Camera.AutoFocusCallback() {                    @Override                    public void onAutoFocus(boolean success, Camera camera) {                        if (success) {                            Log.d("TakePicActivity", "success");                            w = (int) event.getX();                            h = (int) event.getY();//                        setLayout(rlFocus,w-50,h-50);//                        Rect focusRect = calculateTapArea(w,h,100);                            mHandler.obtainMessage(0).sendToTarget();                            initCamera(w, h);                            camera.cancelAutoFocus();//只有加上了这一句,才会自动对焦。                        }                    }                });            }        }else if(event.getAction() == MotionEvent.ACTION_UP){            Log.d(TAG, "onTouchEvent: ACTION_UP");        }        else if(event.getAction() == MotionEvent.ACTION_MOVE){            Log.d(TAG, "onTouchEvent: ACTION_MOVE");        }        return super.onTouchEvent(event);    }    /*     * 覆写返回键监听     */    @Override    public void onBackPressed() {        if (mMediaRecorder != null) {            mMediaRecorder.stop();            mMediaRecorder.release();            mMediaRecorder = null;//            videoRename();        }        finish();    }    @Override    protected void onPause() {        super.onPause();//        onBackPressed();        if (mMediaRecorder != null) {            mMediaRecorder.stop();            mMediaRecorder.release();            mMediaRecorder = null;//            videoRename();        }    }    View view;    private Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch (msg.what) {                case 0:                    flContent.invalidate();                    view = new MyView(TakePicActivity.this, w, h);                    flContent.addView(view);                    mHandler.sendEmptyMessageDelayed(1, 1000);//使选框停留1秒后消失                    break;                case 1:                    flContent.removeView(view);                    break;            }        }    };    /*     * 设置控件所在的位置YY,并且不改变宽高,* XY为绝对位置*/    public void setLayout(View view, int x, int y) {        ViewGroup.MarginLayoutParams margin = new ViewGroup.MarginLayoutParams(view.getLayoutParams());        margin.setMargins(x, y, x + margin.width, y + margin.height);        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(margin);        view.setLayoutParams(layoutParams);    }    File out;    /*    * 生成video文件名字    */    protected void videoRename() {        String path = Environment.getExternalStorageDirectory()                .getAbsolutePath() + "/hfdatabase/video/0/";        String fileName = new SimpleDateFormat("yyyyMMddHHmmss")                .format(new Date()) + ".mp4";        out = new File(path);        if (!out.exists()) {            out.mkdirs();        }        out = new File(path, fileName);        if (mRecAudioFile.exists())            mRecAudioFile.renameTo(out);    }    /*     * 消息提示     */    private Toast toast;    public void showMsg(String arg) {        if (toast == null) {            toast = Toast.makeText(this, arg, Toast.LENGTH_SHORT);        } else {            toast.cancel();            toast.setText(arg);        }        toast.show();    }    /*     * 格式化时间     */    public String format(int i) {        String s = i + "";        if (s.length() == 1) {            s = "0" + s;        }        return s;    }    /*     * 定时器设置,实现计时     */    private Handler handler = new Handler();    private Runnable task = new Runnable() {        public void run() {            if (bool) {                handler.postDelayed(this, 1000);                second++;                if (second >= 60) {                    minute++;                    second = second % 60;                }                if (minute >= 60) {                    hour++;                    minute = minute % 60;                }                timer.setText(format(hour) + ":" + format(minute) + ":" + format(second));            }        }    };    private void startAnimator() {        circleProgress.setVisibility(View.VISIBLE);        animator = ObjectAnimator.ofInt(circleProgress, "progress", progress);        animator.setDuration(60000);        animator.setInterpolator(new LinearInterpolator());        animator.start();    }    /**     * 释放摄像头资源     */    private void freeCameraResource() {        if (camera != null) {            camera.setPreviewCallback(null);            camera.stopPreview();            camera.lock();            camera.release();            camera = null;        }    }    @Override    protected void onDestroy() {        super.onDestroy();        freeCameraResource();        if(mMediaRecorder != null){            mMediaRecorder.release();            mMediaRecorder = null;        }    }}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表