当前位置: 首页 > backend >正文

把Android设备变成“国标摄像头”:GB28181移动终端实战接入指南

把Android设备变成“国标摄像头”:GB28181移动终端实战接入指南

——执法记录仪、巡检终端、布控球,如何通过大牛直播SDK直接挂到GB28181平台?

在过去,GB28181 通常用于固定摄像头、NVR等“设备端”。但在政务、安防、应急等行业,越来越多移动设备(如执法记录仪、巡检终端、布控球等)需要:

像一个“标准国标设备”一样,注册到平台,接收拉流、回放、控制命令,成为移动节点的一部分。

今天,大牛直播SDK 就从实战角度出发,讲讲如何让 Android 设备成为真正的“国标设备客户端”,稳定、高兼容地挂载进各类 GB28181 平台。


一、为什么要做“Android + GB28181 客户端”?

✅ 移动执法

  • 执法现场视频实时上传;

  • 中心平台下发抓拍、录像、对讲命令;

  • 需要在无公网IP下保持连通,适配海康、大华、运营商国标平台、宇视等自研GB平台。

✅ 工业巡检

  • 工人佩戴安卓终端(头戴相机/手持设备)进行视频巡查;

  • 实时接入城市治理平台/安监中台;

  • 需要精准定位(MobilePosition)与定点上报能力。

✅ 应急布控

  • 临时布控设备(布控球、车载设备)现场部署;

  • 无需额外网关,设备即平台节点

  • 断网重连、低码率推送、高容错。


二、Android 作为 GB28181 客户端,要具备哪些核心能力?

大牛直播SDK 的 Android GB28181 接入模块不仅实现了注册、拉流、推送,更是按照 GB/T 28181–2016 和 GB/T 28181–2022 规范,实现了覆盖 90%+ 国标平台实际需求的能力。,目标是“让每一台 Android 设备都能稳定接入国标平台”。

📦 编码与音视频能力扩展

能力描述
✅ 视频编码支持 H.264 / H.265(硬编码自动识别)
✅ 音频编码支持 G.711 A律 / AAC
✅ 编码参数配置支持 GOP、帧率、码率、Profile 设置
✅ 编码控制能力支持软硬编码切换,支持实时静音、音量调节
✅ 屏幕推送支持 Android 5.0+ 版本后台屏幕录制推流
✅ 数据对接支持 YUV/PCM 软编码前数据、H.264/AAC 编码后数据对接
✅ 音频转码Speex、PCMU/PCMA 可转 AAC 进行推送与录制

🔁 协议栈完整实现

功能点支持情况
✅ SIP 注册注销支持 REGISTER / UNREGISTER,支持刷新与超时重注册
✅ 心跳机制支持心跳间隔、重试次数配置
✅ RTP 传输支持 RTP over UDP 和 TCP 被动模式(客户端模式)
✅ PS封装严格按标准封装,支持音视频同步
✅ 目录应答支持平台查询设备目录
✅ 拉流响应支持平台 INVITE,自动应答并启动媒体传输
✅ 移动位置上报支持 MobilePosition 订阅与主动上报 GPS 坐标

🎤 附加指令控制能力(提升“控”和“查”的能力)

控制类型支持内容
✅ 图像抓拍支持平台发起图像抓拍命令,并保存本地或上传
✅ 视频录像支持远程触发录像,录制本地 MP4 文件
✅ 历史回放支持接口联动查询 / 下载 / 回放本地历史文件
✅ 云台控制支持 PTZ 控制命令与预置位操作
✅ 实时水印支持 PNG 图像与文字叠加渲染,含时间戳
✅ 实时快照支持 SDK 内部抓拍当前帧画面
✅ 实时静音/音量控制支持采集端实时切换音频状态,适应突发场景
✅ 降噪支持 VAD 检测、自动增益、环境音降噪

🧩 工程级特性增强(对比常规 SIP 接入)

特性优势
✅ 事件回调机制注册、拉流、错误、断线、重连等都有状态回调
✅ GB28181扩展录像能力支持录制过程中实时暂停/恢复
✅ 逻辑解耦GB28181设备接入回传、录像模块完全独立,可并行控制
✅ 高兼容性多平台、多厂商平台(海康、大华、天翼、宇视等标准国标平台)验证

🧠 应用场景再强化:不仅能看,还能听、控、录、查

行业应用
🛡 公安/交警执法终端音视频上传、实时视频指挥、云台远程控制
🧯 应急救援移动视频布控 + 云台拍摄调度 + 远程定位
🏭 工业巡检移动终端上传、平台远程抓拍、历史录像备份
🚔 城市管理手持终端 + 摄像头联合巡查,接入政务大脑
🎥 车载视频布控摄像头 + 4G/5G上传 + 本地录像存储回传

🧰 项目部署经验建议

项目挑战解决策略
✅ 多GB平台兼容性平台厂商多,建议按 GB28181-2016 为基准,必要时定制注册字段
✅ 定位信息上报使用系统 GPS 与网络融合定位,防止无信号场景定位失败
✅ 低功耗运行可设计后台 Service 长时间运行 + 自动注册+回传+重启机制

✅ 实战总结:真正能上平台的 Android 国标客户端,不能只跑 Demo

市面上很多“国标接入方案”,跑得通 Demo,却在真平台下频繁掉线、无法拉流、音视频失步、SIP崩溃……

而大牛直播SDK Android GB28181 模块:

  • 💪 是从 SIP、编码、传输、封装到底层日志机制全部打通;

  • 📡 是从“平台视角”出发,打造真实国标摄像头行为;

  • 🔄 是能“无感重连、状态感知、链路自修复”的可靠模块;

  • 🧱 是工程落地后,还能让你调、维护、追溯的真正产品。


三、核心代码示例(简化版)

信令处理

GBSIPAgentListener主要系GB28181注册、心跳、DevicePosition等,如注册成功、注册超时、注册网络传输层错误、心跳异常、设备位置请求处理:

public interface GBSIPAgentListener
{/*注册成功* @param dateString: 服务器日期,用来校准设备端时间,用户自行决定是否校准设备时间*/void ntsRegisterOK(String dateString);/**注册超时*/void ntsRegisterTimeout();/**注册网络传输层异常*/void ntsRegisterTransportError(String errorInfo);/**心跳达到异常次数*/void ntsOnHeartBeatException(int exceptionCount, String lastExceptionInfo);/** 设备位置请求, 这个主要用在移动设备位置订阅上* @param interval 请求间隔, 单位是毫秒*/void ntsOnDevicePositionRequest(String deviceId, int interval);
}

GBSIPAgentPlayListener主要系GB28181的Invite、Ack、Bye等处理:

public interface GBSIPAgentPlayListener {/**收到s=Play的实时视音频点播*/void ntsOnInvitePlay(String deviceId, SessionDescription sessionDescription);/**发送play invite response 异常*/void ntsOnPlayInviteResponseException(String deviceId, int statusCode, String errorInfo);/** 收到CANCEL play INVITE请求*/void ntsOnCancelPlay(String deviceId);/** 收到Ack*/void ntsOnAckPlay(String deviceId);/** 收到Bye*/void ntsOnByePlay(String deviceId);/** 不是在收到BYE Message情况下, 终止Play*/void ntsOnTerminatePlay(String deviceId);/** Play会话对应的对话终止, 一般不会出发这个回调,目前只有在响应了200K, 但在64*T1时间后还没收到ACK,才可能会出发收到这个, 请做相关清理处理*/void ntsOnPlayDialogTerminated(String deviceId);
}

GBSIPAgentAudioBroadcastListener主要系GB28181语音广播处理相关,如有语音广播相关需求,可参照demo实例实现:

public interface GBSIPAgentAudioBroadcastListener {/**收到语音广播通知*/void ntsOnNotifyBroadcastCommand(String fromUserName, String fromUserNameAtDomain, String sn, String sourceID, String targetID);/**需要准备接受语音广播的SDP内容*/void ntsOnAudioBroadcast(String commandFromUserName, String commandFromUserNameAtDomain, String sourceID, String targetID);/**音频广播, 发送Invite请求异常*/void ntsOnInviteAudioBroadcastException(String sourceID, String targetID, String errorInfo);/**音频广播, 等待Invite响应超时*/void ntsOnInviteAudioBroadcastTimeout(String sourceID, String targetID);/**音频广播, 收到Invite消息最终响应*/void ntsOnInviteAudioBroadcastResponse(String sourceID, String targetID, int statusCode, SessionDescription sessionDescription);/** 音频广播, 收到BYE Message*/void ntsOnByeAudioBroadcast(String sourceID, String targetID);/** 不是在收到BYE Message情况下, 终止音频广播*/void ntsOnTerminateAudioBroadcast(String sourceID, String targetID);
}

GBSIPAgentDeviceControlListener主要系GB28181设备控制相关,比如远程启动、云台控制:

public interface GBSIPAgentDeviceControlListener {/** 收到远程启动控制命令*/void ntsOnDeviceControlTeleBootCommand(String deviceId, String teleBootValue);/** 云台控制*/void ntsOnDeviceControlPTZCmd(String deviceId, String typeValue);
}

GBSIPAgentQueryCommandListener主要系GB28181查询命令,如预置位查询:

public interface GBSIPAgentQueryCommandListener {/** 设备预置位查询*/void ntsOnDevicePresetQueryCommand(String fromUserName, String fromUserNameAtDomain, String sn, String deviceId);
}

GBSIPAgentTalkListener主要系GB28181语音对讲相关处理:

public interface GBSIPAgentTalkListener {/**收到s=Talk 语音对讲*/void ntsOnInviteTalk(String deviceId, SessionDescription sessionDescription);/**发送talk invite response 异常*/void ntsOnTalkInviteResponseException(String deviceId, int statusCode, String errorInfo);/** 收到CANCEL Talk INVITE请求*/void ntsOnCancelTalk(String deviceId);/** 收到Ack*/void ntsOnAckTalk(String deviceId);/** 收到Bye*/void ntsOnByeTalk(String deviceId);/** 不是在收到BYE Message情况下, 终止Talk*/void ntsOnTerminateTalk(String deviceId);/** Talk会话对应的对话终止, 一般不会出发这个回调,目前只有在响应了200K, 但在64*T1时间后还没收到ACK,才可能会出发收到这个, 请做相关清理处理*/void ntsOnTalkDialogTerminated(String deviceId);
}

GBSIPAgentPlaybackListener系历史视音频回放相关:

public interface GBSIPAgentPlaybackListener {void ntsOnInvitePlayback(long var1, String var3, SessionDescription var4);void ntsOnPlaybackInviteResponseException(long var1, String var3, int var4, String var5);void ntsOnCancelPlayback(long var1, String var3);void ntsOnAckPlayback(long var1, String var3);void ntsOnPlaybackMANSRTSPPlayCommand(long var1, String var3);void ntsOnPlaybackMANSRTSPPauseCommand(long var1, String var3);void ntsOnPlaybackMANSRTSPScaleCommand(long var1, String var3, double var4);void ntsOnPlaybackMANSRTSPSeekCommand(long var1, String var3, double var4);void ntsOnPlaybackMANSRTSPTeardownCommand(long var1, String var3);void ntsOnByePlayback(long var1, String var3);void ntsOnTerminatePlayback(long var1, String var3);void ntsOnPlaybackDialogTerminated(long var1, String var3);
}

GBSIPAgentDownloadListen系历史视音频下载相关:

public interface GBSIPAgentDownloadListener {void ntsOnInviteDownload(long var1, String var3, SessionDescription var4);void ntsOnDownloadInviteResponseException(long var1, String var3, int var4, String var5);void ntsOnCancelDownload(long var1, String var3);void ntsOnAckDownload(long var1, String var3);void ntsOnDownloadMANSRTSPScaleCommand(long var1, String var3, double var4);void ntsOnByeDownload(long var1, String var3);void ntsOnTerminateDownload(long var1, String var3);void ntsOnDownloadDialogTerminated(long var1, String var3);
}

媒体数据处理

RTP数据发送

RTP Sender(SmartPublisherJniV2.java)相关接口设计:

/** SmartPublisherJniV2.java* Author: https://daniusdk.com*/
/** 创建RTP Sender实例** @param reserve:保留参数传0** @return RTP Sender 句柄,0表示失败*/
public native long CreateRTPSender(int reserve);/***设置 RTP Sender传输协议** @param rtp_sender_handle, CreateRTPSender返回值* @param transport_protocol, 0:UDP, 1:TCP, 默认是UDP** @return {0} if successful*/
public native int SetRTPSenderTransportProtocol(long rtp_sender_handle, int transport_protocol);/***设置 RTP Sender IP地址类型** @param rtp_sender_handle, CreateRTPSender返回值* @param ip_address_type, 0:IPV4, 1:IPV6, 默认是IPV4, 当前仅支持IPV4** @return {0} if successful*/
public native int SetRTPSenderIPAddressType(long rtp_sender_handle, int ip_address_type);/***设置 RTP Sender RTP Socket本地端口** @param rtp_sender_handle, CreateRTPSender返回值* @param port, 必须是偶数,设置0的话SDK会自动分配, 默认值是0** @return {0} if successful*/
public native int SetRTPSenderLocalPort(long rtp_sender_handle, int port);/***设置 RTP Sender SSRC** @param rtp_sender_handle, CreateRTPSender返回值* @param ssrc, 如果设置的话,这个字符串要能转换成uint32类型, 否则设置失败** @return {0} if successful*/
public native int SetRTPSenderSSRC(long rtp_sender_handle, String ssrc);/***设置 RTP Sender RTP socket 发送Buffer大小** @param rtp_sender_handle, CreateRTPSender返回值* @param buffer_size, 必须大于0, 默认是512*1024, 当前仅对UDP socket有效, 根据视频码率考虑设置合适的值** @return {0} if successful*/
public native int SetRTPSenderSocketSendBuffer(long rtp_sender_handle, int buffer_size);/***设置 RTP Sender RTP时间戳时钟频率** @param rtp_sender_handle, CreateRTPSender返回值* @param clock_rate, 必须大于0, 对于GB28181 PS规定是90kHz, 也就是90000** @return {0} if successful*/
public native int SetRTPSenderClockRate(long rtp_sender_handle, int clock_rate);/***设置 RTP Sender 目的IP地址, 注意当前用在GB2818推送上,只设置一个地址,将来扩展如果用在其他地方,可能要设置多个目的地址,到时候接口可能会调整** @param rtp_sender_handle, CreateRTPSender返回值* @param address, IP地址* @param port, 端口** @return {0} if successful*/
public native int SetRTPSenderDestination(long rtp_sender_handle, String address, int port);/*** 设置是否开启 RTP Receiver* @param rtp_sender_handle, CreateRTPSender返回值* @param is_enable, 0表示不收RTP包, 1表示收RTP包, SDK默认值为0.* @return*/
public native int EnableRTPSenderReceive(long rtp_sender_handle, int is_enable);/***设置RTP Receiver SSRC** @param rtp_sender_handle, CreateRTPSender返回值* @param ssrc, 如果设置的话,这个字符串要能转换成uint32类型, 否则设置失败** @return {0} if successful*/
public native int SetRTPSenderReceiveSSRC(long rtp_sender_handle, String ssrc);/***设置RTP Receiver Payload 相关信息** @param rtp_sender_handle, CreateRTPSender返回值** @param payload_type, 请参考 RFC 3551** @param encoding_name, 编码名, 请参考 RFC 3551, 如果payload_type不是动态的, 可能传null就好** @param media_type, 媒体类型, 请参考 RFC 3551, 1 是视频, 2是音频** @param clock_rate, 请参考 RFC 3551** @return {0} if successful*/
public native int SetRTPSenderReceivePayloadType(long rtp_sender_handle, int payload_type, String encoding_name, int media_type, int clock_rate);/***设置RTP Receiver PS的pts和dts clock frequency** @param rtp_sender_handle, CreateRTPSender返回值** @param ps_clock_frequency, 默认是90000, 一些特殊场景需要设置** @return {0} if successful*/
public native int SetRTPSenderReceivePSClockFrequency(long rtp_sender_handle, int ps_clock_frequency);/***设置 RTP Receiver 音频采样率** @param rtp_sender_handle, CreateRTPSender返回值* @param sampling_rate, 音频采样率** @return {0} if successful*/
public native int SetRTPSenderReceiveAudioSamplingRate(long rtp_sender_handle, int sampling_rate);/***设置 RTP Receiver 音频通道数** @param rtp_sender_handle, CreateRTPSender返回值* @param channels, 音频通道数** @return {0} if successful*/
public native int SetRTPSenderReceiveAudioChannels(long rtp_sender_handle, int channels);/***初始化RTP Sender, 初始化之前先调用上面的接口配置相关参数** @param rtp_sender_handle, CreateRTPSender返回值** @return {0} if successful*/
public native int InitRTPSender(long rtp_sender_handle);/***获取RTP Sender RTP Socket本地端口** @param rtp_sender_handle, CreateRTPSender返回值** @return 失败返回0, 成功的话返回响应的端口, 请在InitRTPSender返回成功之后调用*/
public native int GetRTPSenderLocalPort(long rtp_sender_handle);/*** UnInit RTP Sender** @param rtp_sender_handle, CreateRTPSender返回值** @return {0} if successful*/
public native int UnInitRTPSender(long rtp_sender_handle);/*** 释放RTP Sender, 释放之后rtp_sender_handle就无效了,请不要再使用** @param rtp_sender_handle, CreateRTPSender返回值** @return {0} if successful*/
public native int DestoryRTPSender(long rtp_sender_handle);
RTP数据接收

对应RTP Receiver(SmartPlayerJniV2.java)相关接口设计,如无语音广播或语音对讲相关技术需求,这部分可忽略:

/** SmartPlayerJniV2.java* Author: https://daniusdk.com*/
/** 创建RTP Receiver** @param reserve:保留参数传0** @return RTP Receiver 句柄,0表示失败*/
public native long CreateRTPReceiver(int reserve);/***设置 RTP Receiver传输协议** @param rtp_receiver_handle, CreateRTPReceiver* @param transport_protocol, 0:UDP, 1:TCP, 默认是UDP** @return {0} if successful*/
public native int SetRTPReceiverTransportProtocol(long rtp_receiver_handle, int transport_protocol);/***设置 RTP Receiver IP地址类型** @param rtp_receiver_handle, CreateRTPReceiver* @param ip_address_type, 0:IPV4, 1:IPV6, 默认是IPV4** @return {0} if successful*/
public native int SetRTPReceiverIPAddressType(long rtp_receiver_handle, int ip_address_type);/***设置 RTP Receiver RTP Socket本地端口** @param rtp_receiver_handle, CreateRTPReceiver* @param port, 必须是偶数,设置0的话SDK会自动分配, 默认值是0** @return {0} if successful*/
public native int SetRTPReceiverLocalPort(long rtp_receiver_handle, int port);/***设置 RTP Receiver SSRC** @param rtp_receiver_handle, CreateRTPReceiver* @param ssrc, 如果设置的话,这个字符串要能转换成uint32类型, 否则设置失败** @return {0} if successful*/
public native int SetRTPReceiverSSRC(long rtp_receiver_handle, String ssrc);/***创建 RTP Receiver 会话** @param rtp_receiver_handle, CreateRTPReceiver* @param reserve, 保留值,目前传0** @return {0} if successful*/
public native int CreateRTPReceiverSession(long rtp_receiver_handle, int reserve);/***获取 RTP Receiver RTP Socket本地端口** @param rtp_receiver_handle, CreateRTPReceiver** @return 失败返回0, 成功的话返回响应的端口, 请在CreateRTPReceiverSession返回成功之后调用*/
public native int GetRTPReceiverLocalPort(long rtp_receiver_handle);/***设置 RTP Receiver Payload 相关信息** @param rtp_receiver_handle, CreateRTPReceiver** @param payload_type, 请参考 RFC 3551** @param encoding_name, 编码名, 请参考 RFC 3551, 如果payload_type不是动态的, 可能传null就好** @param media_type, 媒体类型, 请参考 RFC 3551, 1 是视频, 2是音频** @param clock_rate, 请参考 RFC 3551** @return {0} if successful*/
public native int SetRTPReceiverPayloadType(long rtp_receiver_handle, int payload_type, String encoding_name, int media_type, int clock_rate);/***设置 RTP Receiver 音频采样率** @param rtp_receiver_handle, CreateRTPReceiver* @param sampling_rate, 音频采样率** @return {0} if successful*/
public native int SetRTPReceiverAudioSamplingRate(long rtp_receiver_handle, int sampling_rate);/***设置 RTP Receiver 音频通道数** @param rtp_receiver_handle, CreateRTPReceiver* @param channels, 音频通道数** @return {0} if successful*/
public native int SetRTPReceiverAudioChannels(long rtp_receiver_handle, int channels);/***设置 RTP Receiver 远端地址** @param rtp_receiver_handle, CreateRTPReceiver* @param address, IP地址* @param port, 端口** @return {0} if successful*/
public native int SetRTPReceiverRemoteAddress(long rtp_receiver_handle, String address, int port);/***初始化 RTP Receiver** @param rtp_receiver_handle, CreateRTPReceiver** @return {0} if successful*/
public native int InitRTPReceiver(long rtp_receiver_handle);/***UnInit RTP Receiver** @param rtp_receiver_handle, CreateRTPReceiver** @return {0} if successful*/
public native int UnInitRTPReceiver(long rtp_receiver_handle);/***Destory RTP Receiver Session** @param rtp_receiver_handle, CreateRTPReceiver** @return {0} if successful*/
public native int DestoryRTPReceiverSession(long rtp_receiver_handle);/***Destory RTP Receiver** @param rtp_receiver_handle, CreateRTPReceiver** @return {0} if successful*/
public native int DestoryRTPReceiver(long rtp_receiver_handle);

PostAudioPacket(SmartPlayerJniV2.java),投递音频包给外部Live source,目前仅于语音对讲使用:

/** SmartPlayerJniV2.java* Author: https://daniusdk.com*/
/*** 投递音频包给外部Live source, 注意ByteBuffer对象必须是DirectBuffer** @param handle: return value from SmartPlayerOpen()** @return {0} if successful*/
public native int PostAudioPacket(long handle, int codec_id,java.nio.ByteBuffer packet, int offset, int size, long pts, boolean is_pts_discontinuity,java.nio.ByteBuffer extra_data, int extra_data_offset, int extra_data_size, int sample_rate, int channels);

GB28181接口调用

对应GB28181相关接口调用相关设计如下:

/** SmartPublisherJniV2.java* Author: https://daniusdk.com*/
/*** 设置GB28181 RTP Sender** @param rtp_sender_handle, CreateRTPSender返回值* @param rtp_payload_type, 对于GB28181 PS, 协议定义是96, 具体以SDP为准,  RFC 3551有定义* @param encoding_name, 编码名, 请参考 RFC 3551, 当前仅支持: "PS", 其他值返回失败* @return {0} if successful*/
public native int SetGB28181RTPSender(long handle, long rtp_sender_handle, int rtp_payload_type, String encoding_name);/*** 设置GB28181 RTP 收到的音频包回调* @param handle* @param audio_packet_callback* @return*/
public native int SetGB28181ReceiveAudioPacketCallback(long handle, NTAudioPacketCallback audio_packet_callback);/*** 启动 GB28181 媒体流** @return {0} if successful*/
public native int StartGB28181MediaStream(long handle);/*** 停止 GB28181 媒体流** @return {0} if successful*/
public native int StopGB28181MediaStream(long handle);

四、写在最后:GB28181 客户端,不再只是硬件的专属

随着执法记录仪、智能巡检终端、AI边缘设备等产品的不断演进:

“Android + GB28181 + 实时视频能力”将成为行业新基建的一环。

Android平台GB28181设备接入模块(SmartGBD)目标就是:

  • 让每一台 Android 设备,都能像传统摄像头一样,标准、稳定、低延迟地接入国标平台

  • 帮助开发者快速构建可部署、可维护、可扩展的系统架构,而不只是跑个 Demo。


📖 Android平台GB28181模块接入:Android平台GB28181接入模块技术接入说明

📚 更多实战文章持续更新中:👉 https://daniusdk.blog.csdn.net

http://www.xdnf.cn/news/4083.html

相关文章:

  • 博图V20编译报错:备不受支持,无法编译。请更改为受支持的设备。
  • C++初学者的入门指南
  • [Windows] 批量修改文件/文件夹时间戳工具 NewFileTime 7.71
  • VUE3报错 ReferenceError: Cannot access ‘openInit‘ before initialization
  • 【Qt】配置环境变量
  • educoder平台课-Python程序设计-8.文件
  • 价格识别策略思路
  • 第16章 监控和排除日志记录错误
  • 牛客 Wall Builder II 题解
  • Redis 数据类型详解(二):Hash 类型全解析
  • 数据结构-希尔排序(Python)
  • 立夏三候:蝼蝈鸣,蚯蚓出,王瓜生
  • 【AI学习】DeepSeek-R1是如何训练的?
  • Kdump 收集器及使用方式
  • archlinux安装waydroid
  • 查看并升级Docker里面Jenkins的Java17到21版本
  • 双目测量中的将视差图重投影成三维坐标图
  • 某信服EDR3.5.30.ISO安装测试(二)
  • kotlin 03flow-stateFlow和sharedFlow企业中使用
  • 青听音乐 1.0.6| 全网音乐免费听,无损下载,4条音源,界面简洁无广告
  • Nacos源码—3.Nacos集群高可用分析一
  • 【QT】QT中的软键盘设计
  • C# 方法(局部函数和参数)
  • [前端]异步请求的竞态问题
  • 代码随想录第34天:动态规划7(打家劫舍问题:链式、环式、树式房屋)
  • STA中的multi_cycle 和false_path详细讨论
  • macOS 上是否有类似 WinRAR 的压缩软件?
  • Qt6.8中进行PDF文件读取和编辑
  • LeetCode:返回倒数第k个结点
  • MyBatis 一对多与多对一映射详解教程