通过MediaRecorder实现Android后台循环录像

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.media.MediaRecorder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class RoadRecordService extends Service {
    private static final String TAG = "RoadRecordService";
    //    adb shell am startservice -n .RoadRecordService --ei duration 20000 --ei id 0 --ei height 1080 --ei width 1920
    //    adb shell am stopservice -n .RoadRecordService
    private int video_duration = 10000;
    private int camera_id = 0;
    private int camera_w = 1920;
    private int camera_h = 1080;
    private MediaRecorder mMediaRecorder;
    private WindowManager windowManager;
    private CameraManager cameraManager;
    private CameraDevice cameraDevice;
    private CameraCaptureSession mPreviewSession;
    private CaptureRequest.Builder mPreviewBuilder;
    private CameraDevice.StateCallback mCameraDeviceStateCallback;
    private CameraCaptureSession.StateCallback mSessionStateCallback;
    private CameraCaptureSession.CaptureCallback mSessionCaptureCallback;
    private Handler mChildHandler;
    private int i = 0;
    private boolean isClick = true;
    private Thread clickThread;
    private String root_path;
    private boolean isRecord = false;
    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");;
    private Handler handler = new Handler(Looper.getMainLooper()){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what == 0){
                if (mMediaRecorder!=null){
                    mMediaRecorder.stop();
                    mMediaRecorder.release();
                    mMediaRecorder = null;
                }
                if (mPreviewSession!=null){
                    mPreviewSession.close();
                }
                if (cameraDevice!=null){
                    cameraDevice.close();
                }
                initCamera();
            }
        }
    };
    public RoadRecordService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG,"onCreate");
        root_path = getExternalFilesDir("")+"/video";
        initSurface();
        HandlerThread handlerThread = new HandlerThread("Camera2Demo");
        handlerThread.start();
        mChildHandler = new Handler(handlerThread.getLooper());
        initSessionCaptureCallback();
        initSessionStateCallback();
    }

    @SuppressLint("MissingPermission")
    private void initCamera() {
        cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            cameraManager.openCamera(camera_id + "", new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice camera) {
                    cameraDevice = camera;
                    createBuild();
                }

                @Override
                public void onDisconnected(@NonNull CameraDevice camera) {
                    stopSelf();
                }

                @Override
                public void onError(@NonNull CameraDevice camera, int error) {
                    stopSelf();
                }
            }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
    private void initSurface(){
        windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
        TextView textView = new TextView(this);
        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
                150, 70,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT
        );
        textView.setText("开始录制");
        textView.setBackgroundColor(Color.RED);
        textView.setGravity(Gravity.CENTER);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG,"onClick=====");
                if (isRecord){
                    isRecord = false;
                    stopRecord();
                    textView.setText("开始录制");
                }else {
                    isRecord = true;
                    initCamera();
                    textView.setText("结束录制");
                }
            }
        });
        layoutParams.gravity = Gravity.RIGHT | Gravity.TOP;
        windowManager.addView(textView, layoutParams);
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        video_duration = intent.getIntExtra("duration",10000);
        camera_id = intent.getIntExtra("id",0);
        camera_w = intent.getIntExtra("width",1280);
        camera_h = intent.getIntExtra("height",720);
        Log.i(TAG,"onStartCommand = "+video_duration+";"+camera_id+";"+camera_w+";"+camera_h);
        initCamera();
        startThread();
        return super.onStartCommand(intent, flags, startId);
    }
    private void startThread(){
        clickThread = new Thread(new Runnable() {
            @Override
            public void run() {
                int j = 0;
                while (isClick){
                    Log.i(TAG,"thread = "+j);
                    j++;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        clickThread.start();
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
    private void setUpMediaRecorder() {
        mMediaRecorder = new MediaRecorder();
        //设置用于录制的音源
//        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        //开始捕捉和编码数据到setOutputFile(指定的文件)
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        //设置在录制过程中产生的输出文件的格式
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        //设置输出文件的路径
        mMediaRecorder.setOutputFile(getVideoPath());
        //设置录制的视频编码比特率
        mMediaRecorder.setVideoEncodingBitRate(10000000);
        //设置要捕获的视频帧速率
        mMediaRecorder.setVideoFrameRate(25);
        //设置要捕获的视频的宽度和高度
        mMediaRecorder.setVideoSize(camera_w,camera_h);
        //设置视频编码器,用于录制
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        //设置audio的编码格式
//        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        try {
            mMediaRecorder.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private String getVideoPath(){
        File pathFile = new File(root_path);
        if (!pathFile.exists()){
            pathFile.mkdirs();
        }
        String videoPath = root_path+"/"+simpleDateFormat.format(new Date())+".mp4";
        Log.i(TAG,"videoPath = "+videoPath);
        File videoFile = new File(videoPath);
        try {
            videoFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return videoPath;
    }
    private void createBuild(){
        setUpMediaRecorder();
        try {
            mPreviewBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
            List surfaces = new ArrayList<>();
            Surface recorderSurface = mMediaRecorder.getSurface();
            surfaces.add(recorderSurface);
            mPreviewBuilder.addTarget(recorderSurface);
            // 一旦会话开始,我们就可以更新UI并开始录制
            cameraDevice.createCaptureSession(surfaces, mSessionStateCallback, mChildHandler);
            startRecord();
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
    private void startRecord(){
        Log.i(TAG,"startRecord = "+i);
        i++;
        mMediaRecorder.start();
        deleteFile();
        handler.sendEmptyMessageDelayed(0,video_duration);
    }
    private void initSessionStateCallback(){
        mSessionStateCallback = new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(@NonNull CameraCaptureSession session) {
                mPreviewSession = session;
                try {
                    //执行重复获取数据请求,等于一直获取数据呈现预览画面,mSessionCaptureCallback会返回此次操作的信息回调
                    mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(),mSessionCaptureCallback,mChildHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }

            }

            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession session) {

            }
        };
    }

    private void initSessionCaptureCallback(){
        mSessionCaptureCallback = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) {
                super.onCaptureStarted(session, request, timestamp, frameNumber);
            }

            @Override
            public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
                super.onCaptureProgressed(session, request, partialResult);
            }

            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                super.onCaptureCompleted(session, request, result);
            }

            @Override
            public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) {
                super.onCaptureFailed(session, request, failure);
            }
        };
    }
    private void deleteFile(){
        File rootFile = new File(root_path);
        File[] childFiles = rootFile.listFiles();
        if (childFiles.length > 10){
            long time = 0;
            File delFile = null;
            for (int j = 0; j < childFiles.length; j++) {
                File childFile = childFiles[j];
                String name = childFile.getName();
                String timeStr = name.substring(0,name.lastIndexOf("."));
                Log.i(TAG,"child name = "+timeStr);
                try {
                    long t = simpleDateFormat.parse(timeStr).getTime();
                    if (time == 0){
                        time = t;
                        delFile = childFile;
                    }
                    if (t

你可能感兴趣的:(android,android,studio,java)