您的位置:首页 > 移动开发 > Android开发

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

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

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;

        }

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐