Android实现service 中实现后台录像(附带源码)

Android 实现 Service 中的后台录像功能 —— 项目详解与实战教程

本文将带你一步步实现一个支持在后台运行的摄像头录像功能,即使应用最小化、熄屏甚至切换到其他 App,录像仍可继续进行。

一、项目介绍

在一些特定场景下,如行车记录仪、隐私安防、视频监控、执法记录仪等,Android 设备需要具备在后台持续录像的能力。
这种功能的关键是:即使应用退到后台,也能持续使用摄像头并保存录像文件,甚至可以实现无界面(Headless)运行。

本项目的目标是:

构建一个在 Service 中运行的摄像头后台录像模块,启动后自动进行摄像头初始化与录制,用户可在通知栏控制录像启停,支持前台服务提升系统存活性。


二、相关技术知识详解

1. Camera API 概览

Android 提供两套摄像头 API:

API说明优点缺点
Camera(Camera1)较旧,Android 5.0 以下默认使用简单直接,易于实现功能少,不支持新硬件能力
Camera2(推荐)Android 5.0+ 引入,功能强大高度可控,支持帧率、手动曝光等编码复杂,学习曲线陡峭

本项目使用 Camera2 API,配合 MediaRecorder 实现录制视频。

2. MediaRecorder 组件

  • 用于录音、录像等媒体采集

  • Camera 结合可录制音视频

  • 支持输出格式设置(如 MPEG_4)

3. Foreground Service(前台服务)

  • Android 8.0+ 后系统限制后台服务,需使用前台服务防止被杀死

  • 需要常驻通知栏

  • 使用 startForeground() 启动

4. 权限需求

<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

动态申请:

  • CAMERA

  • RECORD_AUDIO

  • WRITE_EXTERNAL_STORAGE

5. Surface + SurfaceTexture

  • Surface 是摄像头输出图像的目标

  • 在后台无法使用 UI 显示 SurfaceView,因此通过 SurfaceTexture + Surface 绕过可视化限制


三、项目实现思路

  1. 创建 ForegroundService,常驻后台并启动摄像头录像

  2. 使用 Camera2 API 初始化摄像头并连接 MediaRecorder

  3. 配置 MediaRecorder 录制音视频

  4. 利用 SurfaceTexture 作为虚拟图像输出目标

  5. 持续保存录像文件到本地

  6. 在通知栏提供控制按钮:开始 / 停止录像


四、整合代码实现(含详细注释)

项目包结构如下:

com.example.videobackground
│
├── MainActivity.kt         // 启动入口
├── VideoService.kt         // 后台录像前台服务
├── CameraHelper.kt         // 封装 Camera2 + MediaRecorder 逻辑
└── utils/
    └── FileUtils.kt        // 生成文件名工具

1. MainActivity.kt

package com.example.videobackground

import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 请求必要权限
        ActivityCompat.requestPermissions(
            this,
            arrayOf(
                android.Manifest.permission.CAMERA,
                android.Manifest.permission.RECORD_AUDIO,
                android.Manifest.permission.WRITE_EXTERNAL_STORAGE
            ),
            100
        )

        // 启动后台录像服务
        startService(Intent(this, VideoService::class.java))

        finish()
    }
}

2. VideoService.kt

package com.example.videobackground

import android.app.*
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat

class VideoService : Service() {

    private lateinit var cameraHelper: CameraHelper

    override fun onCreate() {
        super.onCreate()

        // 启动前台通知,避免被系统杀死
        createNotificationChannel()
        val notification = NotificationCompat.Builder(this, "video_channel")
            .setContentTitle("后台录像进行中")
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .build()
        startForeground(1, notification)

        // 启动摄像头并录像
        cameraHelper = CameraHelper(this)
        cameraHelper.startRecording()
    }

    override fun onDestroy() {
        super.onDestroy()
        cameraHelper.stopRecording()
    }

    override fun onBind(intent: Intent?): IBinder? = null

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val serviceChannel = NotificationChannel(
                "video_channel",
                "后台录像服务",
                NotificationManager.IMPORTANCE_LOW
            )
            val manager = getSystemService(NotificationManager::class.java)
            manager.createNotificationChannel(serviceChannel)
        }
    }
}

3. CameraHelper.kt

package com.example.videobackground

import android.content.Context
import android.graphics.SurfaceTexture
import android.hardware.camera2.*
import android.media.MediaRecorder
import android.os.Environment
import android.util.Size
import android.view.Surface
import java.io.File
import java.text.SimpleDateFormat
import java.util.*

class CameraHelper(private val context: Context) {

    private lateinit var cameraDevice: CameraDevice
    private lateinit var mediaRecorder: MediaRecorder
    private lateinit var cameraSession: CameraCaptureSession

    private val cameraManager: CameraManager =
        context.getSystemService(Context.CAMERA_SERVICE) as CameraManager

    private lateinit var surface: Surface

    fun startRecording() {
        setupMediaRecorder()
        openCamera()
    }

    fun stopRecording() {
        cameraSession.close()
        cameraDevice.close()
        mediaRecorder.stop()
        mediaRecorder.release()
    }

    private fun setupMediaRecorder() {
        mediaRecorder = MediaRecorder()
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC)
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE)
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
        mediaRecorder.setOutputFile(FileUtils.getOutputMediaFile().absolutePath)
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
        mediaRecorder.setVideoSize(1280, 720)
        mediaRecorder.setVideoFrameRate(30)
        mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024)
        mediaRecorder.prepare()
    }

    private fun openCamera() {
        val cameraId = cameraManager.cameraIdList[0] // 默认使用后摄
        cameraManager.openCamera(cameraId, object : CameraDevice.StateCallback() {
            override fun onOpened(device: CameraDevice) {
                cameraDevice = device
                startSession()
            }

            override fun onDisconnected(device: CameraDevice) {
                device.close()
            }

            override fun onError(device: CameraDevice, error: Int) {
                device.close()
            }
        }, null)
    }

    private fun startSession() {
        val texture = SurfaceTexture(10) // 虚拟Surface,无需显示
        texture.setDefaultBufferSize(1280, 720)
        surface = Surface(texture)

        val recorderSurface = mediaRecorder.surface
        cameraDevice.createCaptureSession(
            listOf(recorderSurface, surface),
            object : CameraCaptureSession.StateCallback() {
                override fun onConfigured(session: CameraCaptureSession) {
                    cameraSession = session
                    val builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD)
                    builder.addTarget(recorderSurface)
                    session.setRepeatingRequest(builder.build(), null, null)

                    mediaRecorder.start()
                }

                override fun onConfigureFailed(session: CameraCaptureSession) {}
            }, null
        )
    }
}

4. FileUtils.kt

package com.example.videobackground.utils

import android.os.Environment
import java.io.File
import java.text.SimpleDateFormat
import java.util.*

object FileUtils {
    fun getOutputMediaFile(): File {
        val mediaStorageDir = File(Environment.getExternalStorageDirectory(), "VideoRecords")
        if (!mediaStorageDir.exists()) {
            mediaStorageDir.mkdirs()
        }
        val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
        return File(mediaStorageDir.path + File.separator + "VID_$timeStamp.mp4")
    }
}

五、方法解读

  • MainActivity::onCreate
    请求权限并启动 VideoService

  • VideoService::onCreate
    创建前台服务并初始化 CameraHelper

  • CameraHelper::startRecording()
    设置 MediaRecorder,打开摄像头,创建会话并开始录制。

  • setupMediaRecorder()
    配置音视频编码、分辨率、帧率、输出路径。

  • openCamera()
    使用 Camera2 打开摄像头,监听回调。

  • startSession()
    创建 CameraCaptureSession 并绑定 MediaRecorder 输出,启动录像。


六、项目总结与拓展

✅ 项目优势

  • 兼容 Android 5.0 以上系统

  • 使用 Camera2 + MediaRecorder 实现高质量录像

  • 支持后台运行与熄屏持续录像

  • 使用 ForegroundService 提高任务存活率

  • 支持本地保存录像文件,方便后期查看/上传

🔧 拓展建议

  1. 支持选择前/后摄

  2. 添加 UI 控制录像按钮

  3. 接入后台上传录像功能

  4. 自动分段录像(每隔10分钟一个文件)

  5. 添加错误重试机制(摄像头失效自动重启)

  6. 结合 Room 保存录像文件元数据

  7. 支持定时停止 / 定时启动


七、结语

后台录像是一个对权限、系统资源管理要求较高的技术点,本项目通过使用 Camera2 + MediaRecorder + ForegroundService 的组合,为 Android 设备构建了一个稳定、可扩展的后台录像解决方案。

这不仅适用于安全监控、行车记录,也为未来的 AI 视觉采集、智能录像等方向打下坚实基础。

如果你喜欢这篇项目文章,欢迎点赞、收藏和留言提问。后续我还将继续推出更多项目实战系列(例如:后台音频录制、分段推流、视频实时上传等)。

如需我将此项目整理为 Markdown 或用于博客发布的版本,也可以告诉我哦!🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值