You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现无需手动点击录制按钮自动启动视频录制并定时停止

实现自动启动并定时停止的视频录制

使用MediaStore.ACTION_VIDEO_CAPTURE无法实现自动录制,因为该Intent会启动系统自带的相机应用,你无法通过代码控制其界面操作(比如自动点击录制/保存按钮)。要实现自动录制,你需要使用自定义相机录制逻辑,推荐使用Jetpack CameraX库,它兼容性好且易于实现。

解决方案步骤

1. 添加CameraX依赖

在模块级build.gradle文件中添加CameraX相关依赖:

dependencies {
    def camerax_version = "1.3.0"
    implementation "androidx.camera:camera-core:$camerax_version"
    implementation "androidx.camera:camera-camera2:$camerax_version"
    implementation "androidx.camera:camera-view:$camerax_version"
}

2. 更新布局文件

在activity_main.xml中添加PreviewView用于显示相机预览:

<androidx.camera.view.PreviewView
    android:id="@+id/previewView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

<Button
    android:id="@+id/record_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="开始录制"
    android:layout_gravity="bottom|center_horizontal"
    android:layout_marginBottom="32dp"/>

3. 修改MainActivity实现自动录制逻辑

替换原有代码为以下实现:

import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.video.MediaStoreOutputOptions;
import androidx.camera.video.Quality;
import androidx.camera.video.QualitySelector;
import androidx.camera.video.Recorder;
import androidx.camera.video.Recording;
import androidx.camera.video.VideoCapture;
import androidx.camera.video.VideoRecordEvent;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.Button;
import android.widget.Toast;

import com.google.common.util.concurrent.ListenableFuture;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {
    private static final int PERMISSION_REQUEST_CODE = 100;
    private static final int RECORD_DURATION_MS = 5000; // 录制时长5秒

    private PreviewView previewView;
    private Button recordBtn;
    private VideoCapture<Recorder> videoCapture;
    private Recording currentRecording;
    private ExecutorService cameraExecutor;
    private Handler handler = new Handler(Looper.getMainLooper());

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        previewView = findViewById(R.id.previewView);
        recordBtn = findViewById(R.id.record_button);
        cameraExecutor = Executors.newSingleThreadExecutor();

        // 检查权限
        if (allPermissionsGranted()) {
            startCamera();
        } else {
            ActivityCompat.requestPermissions(
                    this,
                    new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
                    PERMISSION_REQUEST_CODE
            );
        }

        recordBtn.setOnClickListener(v -> {
            if (currentRecording == null) {
                startRecording();
            }
        });
    }

    private void startCamera() {
        ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);

        cameraProviderFuture.addListener(() -> {
            try {
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();

                // 设置预览用例
                Preview preview = new Preview.Builder().build();
                preview.setSurfaceProvider(previewView.getSurfaceProvider());

                // 设置视频录制用例
                Recorder recorder = new Recorder.Builder()
                        .setQualitySelector(QualitySelector.from(Quality.HIGHEST))
                        .build();
                videoCapture = VideoCapture.withOutput(recorder);

                // 绑定相机用例到生命周期
                CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
                cameraProvider.unbindAll();
                cameraProvider.bindToLifecycle(
                        (LifecycleOwner) this,
                        cameraSelector,
                        preview,
                        videoCapture
                );

            } catch (ExecutionException | InterruptedException e) {
                e.printStackTrace();
            }
        }, ContextCompat.getMainExecutor(this));
    }

    private void startRecording() {
        if (videoCapture == null) return;

        recordBtn.setEnabled(false);
        recordBtn.setText("录制中...");

        // 设置视频输出路径(保存到系统媒体库)
        MediaStoreOutputOptions outputOptions = new MediaStoreOutputOptions.Builder(
                getContentResolver(),
                android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI
        ).build();

        // 开始录制
        currentRecording = videoCapture.getOutput()
                .prepareRecording(this, outputOptions)
                .start(ContextCompat.getMainExecutor(this), recordEvent -> {
                    switch (recordEvent.getEventType()) {
                        case VideoRecordEvent.EVENT_START:
                            // 定时停止录制
                            handler.postDelayed(() -> {
                                if (currentRecording != null) {
                                    currentRecording.stop();
                                }
                            }, RECORD_DURATION_MS);
                            break;
                        case VideoRecordEvent.EVENT_FINALIZE:
                            if (!recordEvent.hasError()) {
                                String msg = "视频已保存: " + recordEvent.getOutputResults().getOutputUri();
                                Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
                            } else {
                                currentRecording.close();
                                currentRecording = null;
                                Toast.makeText(this, "录制失败: " + recordEvent.getError(), Toast.LENGTH_SHORT).show();
                            }
                            recordBtn.setEnabled(true);
                            recordBtn.setText("开始录制");
                            break;
                    }
                });
    }

    private boolean allPermissionsGranted() {
        return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (allPermissionsGranted()) {
                startCamera();
            } else {
                Toast.makeText(this, "需要相机和录音权限才能录制视频", Toast.LENGTH_SHORT).show();
                finish();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cameraExecutor.shutdown();
        handler.removeCallbacksAndMessages(null);
    }
}

关键说明

  • 权限处理: 需要申请CAMERA和RECORD_AUDIO权限,这是录制视频的必要权限。
  • 自动启停: 通过Handler.postDelayed在指定时长后调用Recording.stop()实现自动停止。
  • 视频保存: 使用MediaStoreOutputOptions将视频保存到系统媒体库,无需额外存储权限(Android 10+)。
  • CameraX优势: 自动适配不同设备,简化相机操作逻辑,无需处理复杂的相机兼容性问题。

替代方案

如果无法使用CameraX,也可以使用Camera2 API实现自定义录制,但Camera2的代码复杂度更高,需要处理更多设备兼容性细节。

内容的提问来源于stack exchange,提问作者Adnan Siddique

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 19:35:22