# RTSP安卓播放器 **Repository Path**: lulibo88/rtsp-android-player ## Basic Information - **Project Name**: RTSP安卓播放器 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-03 - **Last Updated**: 2026-09-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # My Application —— rtsp-player 使用案例 本项目是 **rtsp-player** 播放库的使用案例:一个双路 RTSP 摄像头监控 Demo App。 核心为 [`rtsp-player`](./rtsp-player) 模块——基于 [libVLC](https://code.videolan.org/videolan/libvlc-android) 封装的 Android RTSP 播放库,提供「XML 拖入即用」的自定义控件 `RtspPlayerView`,内置自动重连、卡死看门狗、硬件解码、生命周期管理、画面抓拍等能力。Demo App 演示了库的完整接入与使用方式。 ## 模块结构 ``` MyApplication/ ├── rtsp-player/ # 核心:RTSP 播放库(Android Library) │ └── src/main/java/com/dongshi/rtsp/ │ ├── RtspPlayerView.java # 播放控件(公开 API 入口) │ ├── RtspPlayer.java # 播放器实现(基于 libVLC) │ ├── RtspPlayerConfig.java # 播放器配置(Builder 模式) │ ├── RtspPlayerListener.java # 播放状态回调 │ ├── SnapshotCallback.java # 抓拍结果回调 │ └── RtspError.java # 错误码定义 └── app/ # 使用案例:双路摄像头 Demo └── src/main/java/com/dongshi/myapplication/ └── MainActivity.java # 双路播放 + 抓拍保存到相册 ``` ## 环境要求 | 项 | 要求 | |---|---| | Android Studio | 较新版本(项目基于 AGP 8.8.0) | | compileSdk / targetSdk | 35 | | minSdk | 24(Android 7.0) | | Java | 11 | | 依赖库 | libVLC(`org.videolan.android:libvlc-all:3.7.2`) | ## 快速运行 1. 用 Android Studio 打开项目根目录,等待 Gradle 同步完成。 2. 直接运行 `app` 模块,默认预填两个示例 RTSP 地址并自动开始播放。 3. 在输入框修改 RTSP 地址后点击「播放」(或软键盘「前往」键)即可切换流。 > 默认地址是示例用的海康摄像头地址(`MainActivity.java` 中 `DEFAULT_URL_1` / `DEFAULT_URL_2`),请替换为你自己的摄像头地址。 ## 接入 rtsp-player 库 在 `settings.gradle` 中包含模块: ```groovy include ':rtsp-player' ``` 在 app 的 `build.gradle` 中依赖: ```groovy dependencies { implementation project(':rtsp-player') } ``` **打包注意事项(Android 15+ 必读)**:libVLC 原生库按 16KB 页对齐存储,在最终 APK 中必须保持未压缩打包,否则 Android 15+ 设备加载会直接失败。该配置**不随 AAR 传递给接入方**,接入方 app 必须自行声明: ```groovy android { packaging { jniLibs { useLegacyPackaging = true } } } ``` ## 基础用法 ### 1. XML 布局 ```xml ``` ### 2. 播放与状态回调 ```java RtspPlayerView playerView = findViewById(R.id.rtspPlayerView); // 所有回调均在主线程执行,可直接更新 UI playerView.setListener(new RtspPlayerListener() { @Override public void onPlaying() { // 进入播放状态(重连计数清零) } @Override public void onBuffering(float percent) { // 缓冲中,percent 0~100 } @Override public void onReconnecting(int attempt, long delayMs) { // 流断开进入自动重连;attempt 为第几次重试,delayMs 为本次等待时长 } @Override public void onError(int code, String message) { // 无法进入重连流程的错误(空地址、卡死、release 后调用等),code 见 RtspError } }); playerView.play("rtsp://user:password@192.168.1.100:554/streaming/channels/1"); ``` ### 3. 生命周期 控件前后台切换时自动暂停/恢复(attach/detach),只需在宿主销毁时释放: ```java @Override protected void onDestroy() { super.onDestroy(); playerView.release(); // 幂等 } ``` 或绑定生命周期自动释放: ```java playerView.bind(this); // Activity 为 LifecycleOwner,ON_DESTROY 时自动 release() ``` ### 4. 配置 ```java // 需在首次 play() 前调用,默认值适用于大多数场景 playerView.setConfig(RtspPlayerConfig.builder() .autoReconnect(true) // 自动重连,默认 true .reconnectBaseDelayMs(3_000) // 首次重连等待,之后翻倍 .reconnectMaxDelayMs(30_000) // 重连退避封顶 .stallTimeoutMs(15_000) // 卡死判定阈值(时间戳超时未更新) .hwDecoderEnabled(true) // 硬件解码,失败自动软解兜底 .hwDecoderForce(false) // 硬解 direct rendering,默认关(保留取帧能力) .textureView(true) // TextureView 渲染(抓拍依赖此模式) .snapshotFormat(Bitmap.CompressFormat.JPEG) // 抓拍格式 .snapshotQuality(90) // 抓拍质量 0~100 .build()); ``` ### 5. 抓拍 ```java File out = new File(getCacheDir(), "snapshot.jpg"); playerView.snapshot(out, new SnapshotCallback() { @Override public void onSnapshotSuccess(File outputFile) { // 写盘成功(回调在主线程) } @Override public void onSnapshotError(File outputFile, int errorCode, String message) { // 失败,错误码见 RtspError 2xxx } }); ``` ## 错误码(`RtspError`) | 错误码 | 含义 | |---|---| | 1001 | 播放地址为空 | | 1002 | 卡死看门狗触发(时间戳长时间不更新) | | 1003 | release() 之后继续调用播放接口 | | 1004 | 流断开且未开启自动重连 | | 2001 | 抓拍不可用(未开启 TextureView 模式或视图未 attach) | | 2002 | 抓帧失败(无有效画面帧) | | 2003 | 抓拍文件写入失败 | ## 库特性一览 - **XML 拖入即用**:`RtspPlayerView` 自定义控件,布局中直接声明即可 - **自动重连**:断流后按指数退避重连(3s 起,封顶 30s),恢复后重连计数清零 - **卡死看门狗**:播放中时间戳超时未更新判定卡死,强制重连 - **硬件解码**:默认开启,硬解失败自动软解兜底,兼容性优先 - **生命周期自动化**:前后台自动暂停/恢复;支持 `bind(LifecycleOwner)` 自动释放 - **线程安全**:播放控制任意线程可调,所有回调保证在主线程 ## Demo App 功能说明 - 双路 RTSP 摄像头同时播放,每路独立的状态显示、播放/抓拍控制 - RTSP 地址可输入,播放时即时生效;旋转屏幕保留当前地址 - 抓拍图片**保存到系统相册**(`Pictures` 目录): - 库的 `snapshot()` 只能写 `File`,Demo 先抓拍到缓存目录,成功后通过 `MediaStore` 复制进相册 - Android 10+ 走 MediaStore,无需任何存储权限;Android 9 及以下需 `WRITE_EXTERNAL_STORAGE`(`maxSdkVersion="28"`),首次抓拍时弹窗授权 ## 常见问题 **Q:画面黑屏/无法播放?** 确认 RTSP 地址格式正确、摄像头与设备网络互通;观察状态栏提示(连接中/缓冲中/出错)。 **Q:Android 15+ 设备上闪退?** 检查 app 是否声明了 `packaging { jniLibs { useLegacyPackaging = true } }`(见上文打包注意事项),该配置不会从库传递。 **Q:抓拍失败(错误码 2001)?** 抓拍依赖 TextureView 渲染模式(`textureView=true`,默认开启),且视图需已 attach 并有有效画面帧。