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

Android使用声网SDK实现音视频互动(RTC)功能

一、前期准备

1、注册声网账号

声网官网

2、创建项目

拿到AppID,主要证书

二、代码部分

先上一下官方提供的demo地址:

Agora-RTC-QuickStart: 此仓库包含 Agora RTC Native SDK 的QuickStart示例项目。 - Gitee.comhttps://gitee.com/agoraio-community/Agora-RTC-QuickStart/tree/main/Android/Agora-RTC-QuickStart-Android可以在声网的帮助文档中看下图的教程很详细,或者无脑跑上面的demo,只需要填入声网控制台上获取到的appid,证书,和生成的临时token,以及生成临时token时填入的渠道号,但是控制台生成的临时token只有一天的有效期,下面会给出服务端生成临时token的代码,自己部署到服务器上,用客户端去调用接口

服务端:

提供一个获取token的接口

//还没要到代码,后续会补充上来,或者自行去帮助文档中查看,注意是rtc_token

客户端:

1、配置仓库

在settings.gradle中配置,主要是配置镜像

pluginManagement {repositories {maven { url "https://maven.aliyun.com/repository/public" }google()mavenCentral()gradlePluginPortal()}
}
dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories {maven { url "https://maven.aliyun.com/repository/public" }google()mavenCentral()}
}rootProject.name = "你的项目名称"
include ':app'

2、导入声网的sdk

在app模块下的build.gradle的dependencies中加入下面这行,注意下面这个是轻量级的库,详细的库在声网自行搜索

 implementation 'io.agora.rtc:lite-sdk:4.5.1' //替换为最新的

 3、添加防混淆规则

在app模块下的proguard-rules.pro文件中加入下面代码

-keep class io.agora.**{*;}
-dontwarn io.agora.**

4、 静态声明权限

在AndroidManifest.XML文件中声明如下权限

  <uses-featureandroid:name="android.hardware.camera"android:required="true" /><!--必要权限--><uses-permission android:name="android.permission.INTERNET"/><!--可选权限--><uses-permission android:name="android.permission.CAMERA"/><uses-permission android:name="android.permission.RECORD_AUDIO"/><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/><uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/><uses-permission android:name="android.permission.BLUETOOTH"/><!-- 对于 Android 12.0 及以上且集成 v4.1.0 以下 SDK 的设备,还需要添加以下权限 --><uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/><!-- 对于 Android 12.0 及以上设备,还需要添加以下权限 --><uses-permission android:name="android.permission.READ_PHONE_STATE"/><uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>

5、具体代码部分

注:如果需要两个客户端互相传输音视频的话,直接用上面给的官方demo的代码就行,下面介绍的是对官方代码的一些封装,可以满足单西向传输,动态申请权限,调用临时token的接口,token本地存储及校验和不同页面的使用方法

(1)创建bean对象:
import java.io.Serializable/*
* name :相机的名称
* channelName :频道名称 必须唯一
* uid :用户唯一id
* token : 临时token
* lastPostTime :上次成功获取到数据的时间
*/
data class Camera(val name: String,val channelName: String = "",var uid:Int = 0,var token: String? = null,var lastPostTime: Long = 0
) : Serializable
(2)token的本地存储工具类
object SpUtil {private val context = App.app!!val sharedPreferences: SharedPreferences =context.getSharedPreferences("camera", Context.MODE_PRIVATE)//获取绑定的摄像头列表fun getCameraData(): List<Camera> {val listStr = sharedPreferences.getString("list", "")if (listStr == "") {return listOf<Camera>()} else {val typeToken = object : TypeToken<List<Camera>>() {}.typereturn Gson().fromJson(listStr, typeToken)}}//保存绑定的摄像头列表fun saveCameraListData(list: List<Camera>) {sharedPreferences.edit().apply {putString("list", Gson().toJson(list))apply()}}//更新绑定的摄像头列表fun updateCameraData(channelName: String, token: String, uid: Int) {val list = getCameraData().toMutableList()val localCameraList = list.filter { it.channelName == channelName }if (localCameraList.isNotEmpty()) {val localCamera = localCameraList.first()localCameraList.forEach {list.remove(it)}localCamera.token = tokenlocalCamera.lastPostTime = System.currentTimeMillis()localCamera.uid = uidlist.add(localCamera)}saveCameraListData(list)}//检查绑定摄像头的token是否过期fun checkToken(camera: Camera): Boolean {val list = getCameraData()val localCameraList = list.filter { it.channelName == camera.channelName }if (localCameraList.isNotEmpty()) {val localCamera = localCameraList.first()// 判断token是否过期val checkTime = System.currentTimeMillis() - localCamera.lastPostTime <  43200000if (localCamera.token != null && checkTime) {return true}}return false}//获取本地摄像头的数据fun getLocalCameraData(): Camera {val str = sharedPreferences.getString("localCamera", "")if (str == "") {val localCamera = Camera("本机", PlatformApp.getInstance().oaid)saveLocalCameraData(localCamera)return localCamera} else {val typeToken = object : TypeToken<Camera>() {}.typereturn Gson().fromJson(str, typeToken)}}//保存本地摄像头的数据fun saveLocalCameraData(camera: Camera) {sharedPreferences.edit().apply {putString("localCamera", Gson().toJson(camera))apply()}}//检查本地摄像头的token是否过期fun checkLocalCameraData(): Boolean {val localCamera = getLocalCameraData()// 判断token是否过期val checkTime = System.currentTimeMillis() - localCamera.lastPostTime < 43200000return localCamera.token != null && checkTime}
}
(3)RTC的管理类

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import android.view.SurfaceView
import android.widget.FrameLayout
import androidx.core.content.ContextCompat
import com.kwad.sdk.utils.bt.runOnUiThread
import fczs.colorscol.rrjj.base.App
import fczs.colorscol.rrjj.beans.Camera
import io.agora.rtc2.ChannelMediaOptions
import io.agora.rtc2.Constants
import io.agora.rtc2.IRtcEngineEventHandler
import io.agora.rtc2.RtcEngine
import io.agora.rtc2.RtcEngineConfig
import io.agora.rtc2.video.VideoCanvas
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.Call
import okhttp3.Callback
import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.json.JSONObject
import java.io.IOException
import kotlin.coroutines.resumeclass RtcManger {private val baseContext = App.app!!// 填写项目的 App ID,可在声网控制台中生成private val appId = "你的AppId"//临时tokenvar token = ""//uid每个渠道应保持唯一性,为0的话,sdk会自动分配一个,但如果临时token是自己服务器生成的,那就应该保持和服务给的一致,否则token鉴权不过,无法加入渠道var uid = 0//要加入的渠道var channelName = "";private var mRtcEngine: RtcEngine? = null//权限回调码val PERMISSION_REQ_ID: Int = 22//远程视频视图容器var remoteVideoViewContainer: FrameLayout? = null//本地视图容器var localVideoViewContainer: FrameLayout? = nullprivate val mRtcEventHandler: IRtcEngineEventHandler = object : IRtcEngineEventHandler() {// 监听频道内的远端用户,获取用户的 uid 信息override fun onUserJoined(uid: Int, elapsed: Int) {runOnUiThread { // 获取 uid 后,设置远端视频视图setupRemoteVideo(uid)}}override fun onUserOffline(uid: Int, reason: Int) {super.onUserOffline(uid, reason)runOnUiThread {remoteVideoViewContainer?.removeAllViews()}}}fun init(camera: Camera) {this.channelName = camera.channelNamethis.token = camera.token ?: ""this.uid = camera.uid}/** clientRoleType: 用户角色类型,默认为 Constants.BROADCASTER (主播) 发送方 ,还可以是Constants.CLIENT_ROLE_AUDIENCE(观众) 接收方* localVideoViewContainer: 本地视频视图容器* remoteVideoViewContainer: 远端视频视图容器*/fun initializeAndJoinChannel(clientRoleType: Int = Constants.CLIENT_ROLE_BROADCASTER,localVideoViewContainer: FrameLayout? = null,remoteVideoViewContainer: FrameLayout? = null) {this.remoteVideoViewContainer = remoteVideoViewContainerthis.localVideoViewContainer = localVideoViewContainertry {// 创建 RtcEngineConfig 对象,并进行配置val config = RtcEngineConfig()config.mContext = baseContextconfig.mAppId = appId//添加远端视频视图handlerif (remoteVideoViewContainer != null) {config.mEventHandler = mRtcEventHandler}// 创建并初始化 RtcEnginemRtcEngine = RtcEngine.create(config)} catch (e: Exception) {throw RuntimeException("Check the error.")}// 启用视频模块mRtcEngine!!.enableVideo()//本地视图显示if (localVideoViewContainer != null) {// 开启本地预览mRtcEngine!!.startPreview()// 创建一个 SurfaceView 对象,并将其作为 FrameLayout 的子对象val container = localVideoViewContainerval surfaceView = SurfaceView(baseContext)container.addView(surfaceView)// 将 SurfaceView 对象传入声网实时互动 SDK,设置本地视图mRtcEngine!!.setupLocalVideo(VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_FIT, 0))}// 创建 ChannelMediaOptions 对象,并进行配置val options = ChannelMediaOptions()// 根据场景将用户角色设置为 BROADCASTER (主播) 或 AUDIENCE (观众)options.clientRoleType = clientRoleType// 直播场景下,设置频道场景为 BROADCASTING (直播场景)options.channelProfile = Constants.CHANNEL_PROFILE_LIVE_BROADCASTING// 使用临时 Token 加入频道,自行指定用户 ID 并确保其在频道内的唯一性mRtcEngine!!.joinChannel(token, channelName, uid, options)}// 获取体验实时音视频互动所需的录音、摄像头等权限fun getRequiredPermissions(): Array<String> {// 判断 targetSDKVersion 31 及以上时所需的权限return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {arrayOf(Manifest.permission.RECORD_AUDIO,  // 录音权限Manifest.permission.CAMERA,  // 摄像头权限Manifest.permission.READ_PHONE_STATE,  // 读取电话状态权限Manifest.permission.BLUETOOTH_CONNECT, // 蓝牙连接权限)} else {arrayOf(Manifest.permission.RECORD_AUDIO,Manifest.permission.CAMERA)}}private fun setupRemoteVideo(uid: Int) {if (remoteVideoViewContainer != null) {val container = remoteVideoViewContainer!!val surfaceView = SurfaceView(baseContext)surfaceView.setZOrderMediaOverlay(true)container.addView(surfaceView)// 将 SurfaceView 对象传入声网实时互动 SDK,设置远端视图mRtcEngine!!.setupRemoteVideo(VideoCanvas(surfaceView,VideoCanvas.RENDER_MODE_FIT,uid))}}fun checkPermissions(context: Context): Boolean {for (permission in getRequiredPermissions()) {val permissionCheck = ContextCompat.checkSelfPermission(context, permission)if (permissionCheck != PackageManager.PERMISSION_GRANTED) {return false}}return true}fun close() {// 停止本地视频预览mRtcEngine?.stopPreview()// 离开频道mRtcEngine?.leaveChannel()localVideoViewContainer?.removeAllViews()}//获取后台数据  channelName:渠道名称  expire: 获取到的临时token的有效时间  localCamera: 是否是本地摄像头(摄像)suspend fun requestData(channelName: String, localCamera: Boolean = false): String {return suspendCancellableCoroutine { continuation ->val fromBody = FormBody.Builder().add("channelName",channelName).add("uid","能保持唯一性的字符串,如设备的oaid").build()val request = Request.Builder().url("自己服务器接口的url").post(fromBody).build()// 发起异步请求OkHttpClient().newCall(request).enqueue(object : Callback {override fun onResponse(call: Call, response: Response) {if (response.isSuccessful) {try {val responseBody = response.body?.string() ?: ""val jsonObject = JSONObject(responseBody)val code = jsonObject.getInt("code")if (code == 200) {var data = jsonObject.getJSONObject("data")val token = data.getString("token")val uid = data.getInt("uid")this@RtcManger.channelName = channelNamethis@RtcManger.token = tokenthis@RtcManger.uid = uidif (localCamera) {//更新本机摄像头发送视图时的数据SpUtil.saveLocalCameraData(Camera("本机", channelName, uid, token, System.currentTimeMillis()))} else {//更新本地存储的绑定摄像头的数据SpUtil.updateCameraData(channelName, token, uid)}continuation.resume("true")} else {continuation.resume("false")}} catch (e: Exception) {// JSON 解析失败continuation.resume("false")Log.e("Request failed", "Json解析失败:" + e.message.toString())}}}override fun onFailure(call: Call, e: IOException) {continuation.resume("false")Log.e("Request failed", "请求失败:" + e.message.toString())}})}}
}
(4)发送音视频界面
界面:

确报有一个下面的布局就行

  <FrameLayoutandroid:id="@+id/local_video_view_container"android:layout_width="match_parent"android:layout_height="match_parent"/>
代码:

在activity/fragment中声明如下变量和方法,示例中发送端是fragment,后面接收端是activity的示例代码

private val rtcManger = RtcManger()
private val localCamera by lazy { SpUtil.getLocalCameraData() }//正常动态申请权限应该在activity的结果回调方法中写,但如果在onResume中执行判断就可以不用写结果回调方法
override fun onResume() {super.onResume()// 如果已经授权,则初始化 RtcEngine 并加入频道if (rtcManger.checkPermissions(requireContext())) {binding.permissionLL.container.visibility = View.GONEcheckToken()} else {//显示无权限布局binding.permissionLL.apply {container.visibility = View.VISIBLEpermissionBt.setOnClickListener {ActivityCompat.requestPermissions(requireActivity(),rtcManger.getRequiredPermissions(),rtcManger.PERMISSION_REQ_ID)}}}}private fun checkToken() {binding.permissionLL.container.visibility = View.GONEif (SpUtil.checkLocalCameraData()) {rtcManger.init(localCamera)start()} else {CoroutineScope(Dispatchers.Main).launch {connectDialog.show()val result = withContext(Dispatchers.IO) {rtcManger.requestData(localCamera.channelName, true)}.toBoolean()connectDialog.dismiss()if (result) {start()} else {Toast.makeText(requireContext(), "服务器异常,请稍后重试", Toast.LENGTH_SHORT).show()}}}}private fun start() {rtcManger.initializeAndJoinChannel(Constants.CLIENT_ROLE_BROADCASTER,binding.localVideoViewContainer)}private fun stop() {rtcManger.close()}override fun onPause() {super.onPause()stop()}
 (5)接收音视频界面
界面:
    <FrameLayoutandroid:id="@+id/remote_video_view_container"android:layout_width="match_parent"android:layout_height="match_parent" />
代码: 

和上面发送的大差不差,只是进入acticity时传递了要发送端的Camera对象,里面有渠道号,token等信息,这些发送端在拉token的时候已经通过SpUtil存到本地了,自己读取一下需要的

private lateinit var camera: Camerapublic override fun onCreate(savedInstanceState: Bundle?) {camera = intent.getSerializableExtra("camera") as Camera}override fun onResume() {super.onResume()// 如果已经授权,则初始化 RtcEngine 并加入频道if (rtcManger.checkPermissions(this)) {binding.permissionLL.container.visibility = View.GONEcheckToken()} else {binding.permissionLL.apply {container.visibility = View.VISIBLEpermissionBt.setOnClickListener {ActivityCompat.requestPermissions(this@CameraActivity,rtcManger.getRequiredPermissions(),rtcManger.PERMISSION_REQ_ID)}}}
}@Deprecated("Deprecated in Java")override fun onRequestPermissionsResult(requestCode: Int,permissions: Array<String?>,grantResults: IntArray) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)// 系统权限申请回调if (rtcManger.checkPermissions(this)) {checkToken()}}private fun checkToken() {binding.permissionLL.container.visibility = View.GONEif (SpUtil.checkToken(camera)) {rtcManger.init(camera)start()} else {CoroutineScope(Dispatchers.Main).launch {connectDialog.show()val result = withContext(Dispatchers.IO) {rtcManger.requestData(camera.channelName)}.toBoolean()if (result) {connectDialog.dismiss()start()} else {connectDialog.showFailView {finish()}}}}}fun start() {rtcManger.initializeAndJoinChannel(Constants.CLIENT_ROLE_AUDIENCE,null,binding.remoteVideoViewContainer)}override fun onPause() {super.onPause()binding.remoteVideoViewContainer.removeAllViews() rtcManger.close()}

ok,就是这样,总体来说是很简单的,发送端和接收端只是start方法不一样,其余的都差不多,希望上面的经验能帮到你

相关文章:

Android使用声网SDK实现音视频互动(RTC)功能

一、前期准备 1、注册声网账号 声网官网 2、创建项目 拿到AppID&#xff0c;主要证书 二、代码部分 先上一下官方提供的demo地址&#xff1a; Agora-RTC-QuickStart: 此仓库包含 Agora RTC Native SDK 的QuickStart示例项目。 - Gitee.comhttps://gitee.com/agoraio-comm…...

【go】slice的浅拷贝和深拷贝

浅拷贝(Shallow Copy) 浅拷贝是指只复制切片本身的结构&#xff08;指针、长度和容量&#xff09;&#xff0c;而不复制底层数组的元素。 实现方式 直接赋值&#xff1a; slice1 : []int{1, 2, 3} slice2 : slice1 // 浅拷贝切片操作&#xff1a; slice1 : []int{1, 2, 3} s…...

哑铃图:让数据对比一目了然【Dumbbell Chart】

没错&#xff0c;当我祭出 “哑铃” 阵列&#xff0c;你当如何破解&#xff0c;哈哈哈哈…此时&#xff0c;你可以适当怀疑笔者的精神状态了。但话说回来&#xff0c;如果稍加想象&#xff0c;把上图竖起来&#xff0c;“大致” 就是我要分享的 “哑铃图” 了。&#x1f611; …...

Spring Boot 集成 MongoDB 时自动创建的核心 Bean 的详细说明及表格总结

以下是 Spring Boot 集成 MongoDB 时自动创建的核心 Bean 的详细说明及表格总结&#xff1a; 核心 Bean 列表及详细说明 1. MongoClient 类型&#xff1a;com.mongodb.client.MongoClient作用&#xff1a; MongoDB 客户端核心接口&#xff0c;负责与 MongoDB 服务器建立连接、…...

水产养殖水下监控无人机推荐-P200PRO

水产养殖水下监控无人机推荐 | 潜 鲛 P200 PRO&#xff1a;您的“水下管家”&#xff0c;养鱼增产、降本增效的终极利器&#xff01; ——上海 棕航电子 科技&#xff0c;用技术守护每一方鱼塘 一、水产养殖的痛点&#xff1a;看不见的水下&#xff0c;才是赚钱的关键 …...

数据结构与算法-数学-基础数学算法(筛质数,最大公约数,最小公倍数,质因数算法,快速幂,乘法逆元,欧拉函数)

一&#xff1a;筛质数&#xff1a; 1-埃氏筛法 该算法核心是从 2 开始&#xff0c;把每个质数的倍数标记为合数&#xff0c;时间复杂度约为 O(nloglogn)。 #include <iostream> #include <vector>u sing namespace std; const int N 1000010; bool st[N]; …...

elasticSearch-搜索引擎

搜索引擎的优势 有了数据库分页查询&#xff0c;为什么还需要搜索引擎&#xff1f; 搜索引擎速度上很快数据库分页查询&#xff0c;随着数据库数据量增大&#xff0c;页数靠后&#xff0c;会导致搜索速度变慢&#xff0c;但是搜索引擎不会搜索引擎支持分词查询&#xff0c;地…...

MQTT-Dashboard-数据集成

sink [sɪŋk] 下沉&#xff1b;沉没&#xff1b;沉降&#xff1b;...

uni-app项目运行在浏览器、微信开发者工具、mumu模拟器

一、安装HBuilder X 1、下载HBuilder X 官网网址&#xff1a;https://dcloud.io/hbuilderx.html 根据电脑系统下载对应的版本&#xff08;我的电脑是Windows 10&#xff09; 2.安装HBuilder X 直接将HBuilderX.4.61.2025040322-alpha.zip解压到自己想要存放的文件夹中 双击…...

从零开始微调Embedding模型:基于BERT的实战教程

文章目录 背景微调实战装包介绍 项目文件介绍微调硬件配置要求 debug 重要代码分析【选看】资源分享参考资料 背景 在理解与学会了Naive RAG的框架流程后&#xff0c;就很自然地关注到embedding模型&#xff0c;与问题相关的文本召回&#xff0c;也有很多论文在做这方面的创新…...

机器学习(神经网络基础篇)——个人理解篇5(梯度下降中遇到的问题)

在神经网络训练中&#xff0c;计算参数的梯度是关键步骤。numerical_gradient 方法旨在通过数值微分&#xff08;中心差分法&#xff09;计算损失函数对网络参数的梯度。然而&#xff0c;该方法的实现存在一个关键问题&#xff0c;导致梯度计算错误。 1、错误代码示例&#xf…...

带label的3D饼图(threejs)

3D饼图 使用three.js实现&#xff0c;选择threejs的原因&#xff1a;label需要实际的显示在具体的饼对应的模块上 “three”: “^0.127.0”, <template><div><div ref"chartContainer" class"chart-container"></div><div clas…...

ragflow开启https访问:使用自签证书还是有不安全警告,如何解决

背景:在ragflow里的使用了自签证书来启动ragflow,在浏览器里访问还是不安全警告,如何解决 在方案2中,证书不会在访问网站时自动下载,需要你手动获取并安装证书文件。以下是具体操作步骤: 详细步骤:手动获取并安装自签名证书 第一步:获取证书文件 找到证书文件 证书文件位…...

条件变量核心要素

条件变量内部实现原理 原子性解锁阻塞机制&#xff1a; // pthread_cond_wait内部伪代码大致如下&#xff1a; int pthread_cond_wait(cond_t *cond, mutex_t *mutex) {atomic {unlock(mutex); // 原子操作中先释放互斥锁block_thread(); // 立即将线程加入等待队列…...

C语言求鞍点

我们先在第一行中找出最大的值&#xff0c;然后在该列中找出最小值看这两个是否相等。 若是相等&#xff0c;那么这个数就是鞍点跳出循环 若是不想等&#xff0c;则继续在下一行寻找&#xff0c;若是一直到整体的循环都结束了还是没有&#xff0c;那么不存在鞍点。 运行结果:…...

XELA机器人多种“形态和玩法”的Uskin磁性阵列式三轴触觉传感器,你使用过了吗?

XELA Robotics为机器人行业提供创新的磁性触觉传感技术&#xff0c;uSkin触觉传感器是一种高密度的三轴触觉传感器&#xff0c;因其轻薄、表面柔软耐用和布线少的结构设计&#xff0c;可以轻松集成到机器人本体&#xff0c;灵巧手&#xff0c;机器人夹爪等部位&#xff0c;使机…...

转换效率高达 96%,12V转5V同步降压WD5030

特点1 宽输入电压范围&#xff1a;能在 7V 至 30V 的宽输入电压范围内工作&#xff0c;可适应多种不同电压等级的供电环境&#xff0c;无论是工业设备中的较高电压输入&#xff0c;还是便携式设备经过初步升压后的电压&#xff0c;都能良好适配&#xff0c;极大地拓展了应用的…...

请你回答一下单元测试、集成测试、系统测试、验收测试、回归测试这几步中最重要的是哪一步?

在软件测试的不同阶段中,每个环节都有其不可替代的价值,但若从工程效率和缺陷防控的全局视角来看,单元测试(Unit Testing) 是质量金字塔的基石,其重要性最为关键。以下是分层解析: 一、从缺陷修复成本看优先级 美国国家标准与技术研究院(NIST)研究显示: 单元测试阶段…...

QML和C++交互

目录 1 QML与C交互基础1.1 全局属性1.2 属性私有化(提供接口访问) 2 QT与C交互&#xff08;C创建自定义对象&#xff0c;qml文件直接访问&#xff09;3 QT与C交互&#xff08;qml直接访问C中的函数&#xff09;4 QT与C交互&#xff08;qml端发送信号 C端实现槽函数&#xff09;…...

2021年-全国大学生数学建模竞赛(CUMCM)试题速浏、分类及浅析

2021年-全国大学生数学建模竞赛(CUMCM)试题速浏、分类及浅析 全国大学生数学建模竞赛(China Undergraduate Mathematical Contest in Modeling)是国家教委高教司和中国工业与应用数学学会共同主办的面向全国大学生的群众性科技活动,目的在于激励学生学习数学的积极性,提高学…...

mariadb使用docker compose方式安装

问题 本地mac m1上面的mysql和mariadb突然不用使用了&#xff0c;重新安装也不想&#xff0c;最近mac系统也更新了&#xff0c;brew也更新了&#xff0c;重新安装mariadb还是不能正常使用&#xff0c;现在我打算使用docker来安装本地的mariadb了。 默认配置文件my.cnf 从容器…...

Logo语言的死锁

Logo语言的死锁现象研究 引言 在计算机科学中&#xff0c;死锁是一个重要的研究课题&#xff0c;尤其是在并发编程中。它指的是两个或多个进程因争夺资源而造成的一种永久等待状态。在编程语言的设计与实现中&#xff0c;如何避免死锁成为了优化系统性能和提高程序可靠性的关…...

具身智能零碎知识点(一):深入解析Transformer位置编码

深入解析Transformer位置编码 Transformer位置编码完全解析&#xff1a;从公式到计算的终极指南一、位置编码的必要性演示二、位置编码公式深度拆解原始公式参数说明&#xff08;以d_model4为例&#xff09; 三、完整计算过程演示步骤1&#xff1a;计算频率因子步骤2&#xff1…...

0201概述-机器学习-人工智能

文章目录 1、概述1.1、示例1.2、概念 2、应用场景2.1、行业应用场景2.1.1、金融领域2.1.2、 医疗健康2.1.3、零售与电商2.1.4、 制造业2.1.5、自动驾驶 2.2、功能场景分类2.2.1、 预测类2.2.2、分类与识别类2.2.3、生成与优化类 2.3、机器学习适用场景的共同特征 3、实现机器学…...

金能电力工具柜:“五世同堂”演绎创新华章

在电力与工业领域的浩瀚星空中&#xff0c;金能电力如同一颗璀璨的星辰&#xff0c;其工具柜产品更是经历了五代更迭&#xff0c;如同家族中的“五世同堂”&#xff0c;每一代都承载着前人的智慧与后人的创新&#xff0c;共同谱写着传承与创新的交响曲。 初识平凡&#xff1a;普…...

蓝桥杯每日刷题c++

目录 P9240 [蓝桥杯 2023 省 B] 冶炼金属 - 洛谷 (luogu.com.cn) P8748 [蓝桥杯 2021 省 B] 时间显示 - 洛谷 (luogu.com.cn) P10900 [蓝桥杯 2024 省 C] 数字诗意 - 洛谷 (luogu.com.cn) P10424 [蓝桥杯 2024 省 B] 好数 - 洛谷 (luogu.com.cn) P8754 [蓝桥杯 2021 省 AB2…...

MySQL基础 [五] - 表的增删查改

目录 Create&#xff08;insert&#xff09; Retrieve&#xff08;select&#xff09; where条件 ​编辑 NULL的查询 结果排序(order by) 筛选分页结果 (limit) Update Delete 删除表 截断表&#xff08;truncate&#xff09; 插入查询结果&#xff08;insertselect&…...

深入解析 MySQL 中的日期时间函数:DATE_FORMAT 与时间查询优化

深入解析 MySQL 中的日期时间函数&#xff1a;DATE_FORMAT 与时间查询优化 在数据库管理和应用开发中&#xff0c;日期和时间的处理是不可或缺的一部分。MySQL 提供了多种日期和时间函数来满足不同的需求&#xff0c;其中DATE_FORMAT函数以其强大的日期格式化能力&#xff0c;…...

GPU是什么? 与 FPGA 有何关联

前段时间&#xff0c;AMD 和英伟达相继接到通知将对我国断供高端 GPU 芯片&#xff0c;很多人这才意识到 GPU 的战略价值。那么 GPU 究竟是什么&#xff1f;它为何如此重要&#xff1f;今天就由 宸极教育 带大家一起了解 GPU 的核心地位&#xff0c;以及它与国产FPGA发展的关系…...

数据结构与算法:基础与进阶

&#x1f31f; 各位看官好&#xff0c;我是maomi_9526&#xff01; &#x1f30d; 种一棵树最好是十年前&#xff0c;其次是现在&#xff01; &#x1f680; 今天来学习C语言的相关知识。 &#x1f44d; 如果觉得这篇文章有帮助&#xff0c;欢迎您一键三连&#xff0c;分享给更…...

低配置云服务器网站的高效防御攻略

在网络环境日益复杂的当下&#xff0c;低配置云服务器网站常面临攻击威胁。不少站长疑惑&#xff0c;明明设置了 CC 防御&#xff0c;服务器却依旧不堪一击&#xff0c;这是怎么回事呢&#xff1f; 比如&#xff0c;在 CC 防御配置中&#xff0c;设定 10 秒内允许访问 50 次。但…...

使用 Lua 脚本高效查询 Redis 键的内存占用

使用 Lua 脚本高效查询 Redis 键的内存占用 在处理 Redis 数据时&#xff0c;我们常常需要了解某些键的内存占用情况&#xff0c;尤其是在优化内存使用或排查问题时。虽然 Redis 提供了MEMORY USAGE命令来查询单个键的内存占用&#xff0c;但如果需要批量查询多个键&#xff0…...

【Linux篇】基础IO - 揭秘重定向与缓冲区的管理机制

&#x1f4cc; 个人主页&#xff1a; 孙同学_ &#x1f527; 文章专栏&#xff1a;Liunx &#x1f4a1; 关注我&#xff0c;分享经验&#xff0c;助你少走弯路&#xff01; 文章目录 一. 理解重定向1.1 理解重定向1.2 dup21.3 进一步理解重定向输出重定向&#xff1a;追加重定向…...

centos 8 启动Elasticsearch的时候报内存不足问题解决办法

centos 8 启动Elasticsearch 的时候报错,导致无法启动Elasticsearch 。 [root@CentOS-8 ~]# journalctl -xe Apr 07 18:25:56 CentOS-8.0 kernel: [ 8754] 0 8754 3180 63 69632 0 0 sh Apr 07 18:25:56 CentOS-8.0 kernel: [ 8755] 0 8755 3180 64 69632 0 0 sh Apr 07 18:25…...

深入剖析Java IO设计模式:从底层原理到实战应用

&#x1f50d; 引言&#xff1a;设计模式与IO的完美交响 在软件开发的浩瀚星河中&#xff0c;设计模式犹如璀璨的导航星&#xff0c;而Java IO体系则是支撑数据流动的神经网络。 当我们以设计模式的视角重新审视Java IO库时&#xff0c;会发现这个看似平凡的IO世界实则暗藏着…...

阶段测试 【过程wp】

分享总结: 回顾起来,真的感慨很多呀。看着并不难啊,但难的是解题思维:如何判断该页面的关键点,快速地确定问题的核心,找到对应的解决方法。达到便捷、高效的得到结果。我们做了整整近七个半小时。在这个过程中,我发现自己的思维钝化,不太能自主高效地划分判断漏洞类型,…...

qml信号与槽函数

目录 信号与槽函数基础方法1-使用Connections方式2-使用connect&#xff08;不常用&#xff09; 自定义组件与信号槽使用 信号与槽函数基础 方法1-使用Connections main.qml import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15Window {id:windoww…...

ngx_palloc

定义在 src\core\ngx_palloc.c void * ngx_palloc(ngx_pool_t *pool, size_t size) { #if !(NGX_DEBUG_PALLOC)if (size < pool->max) {return ngx_palloc_small(pool, size, 1);} #endifreturn ngx_palloc_large(pool, size); } 判断 需要分配的内存大小 是否小于 poo…...

notepad++日常使用(每行开头、每行末尾增加字符串,每行中间去掉字符串)

1. 每行开头增加字符串 如果我们要给下面的数据每行的开头都增加相同的一些字符串{value: 这时候只需要使用notepad的语法&#xff0c;使用快捷键Crtl H 替换功能&#xff0c;每一行开头使用 ^ 符号&#xff0c;替换成自己想要的字符串 {value: 使用全部替换就会在每行数据…...

Java面试黄金宝典39

1. SNMP、SMTP 协议 SNMP(简单网络管理协议) 定义:SNMP 是一种应用层协议,用于在 IP 网络中管理网络节点(如服务器、路由器、交换机等)。它允许网络管理员监控网络设备的状态、收集性能数据、进行故障诊断等操作。SNMP 基于 UDP 协议,采用轮询和事件驱动相结合的方式来收…...

如何解决:http2: Transport received Server‘s graceful shutdown GOAWAY

有一次做压力测试&#xff0c;客户端经常出现如下错误&#xff1a; http2: Transport: cannot retry err [http2: Transport received Servers graceful shutdown GOAWAY] after Request.Body was written; define Request.GetBody to avoid this error是 Golang 中使用 HTTP/…...

贪心算法(16)(java)俄罗斯套娃信封问题

题目&#xff1a;给你一个二维整数数组 envelopes &#xff0c;其中 envelopes[i] [wi, hi] &#xff0c;表示第 i 个信封的宽度和高度。 当另一个信封的宽度和高度都比这个信封大的时候&#xff0c;这个信封就可以放进另一个信封里&#xff0c;如同俄罗斯套娃一样。 请计算…...

【DeepSeek原理学习2】MLA 多头隐变量注意力

解决的问题 Multi-Head Latent Attention&#xff0c;MLA——解决的问题&#xff1a;KV cache带来的计算效率低和内存需求大以及上下文长度扩展问题。 MLA原理 MLA原理&#xff1a;其核心思想是将键&#xff08;Key&#xff09;和值&#xff08;Value&#xff09;矩阵压缩到…...

2024年RAG大赛

2024 CCF国际AIOps挑战赛赛题与赛制解读-CSDN博客 自动化测评也比较有意思&#xff0c;分数为 关键字 语义相似度&#xff0c;分值比为6:4. 2024 CCF AIOPS国际挑战赛优秀奖方案分享 https://zhuanlan.zhihu.com/p/7444390758 【大模型RAG获奖方案分享】如何提高RAG系统在…...

2025-4-6-C++ 学习 有序数组、set()的一些内置函数与求和函数

C的学习必须更加精进一些&#xff0c;对于好多的函数和库的了解必须深入一些。 文章目录 3510. 移除最小数对使数组有序 II&#xff08;有序数组&#xff09;题目参考代码&#xff08;1&#xff09;auto it idx.lower_bound(i);功能解释可能的使用场景常见错误 &#xff08;2&…...

Flutter:Flutter SDK版本控制,fvm安装使用

1、首先已经安装了Dart&#xff0c;cmd中执行 dart pub global activate fvm2、windows配置系统环境变量 fvm --version3、查看本地已安装的 Flutter 版本 fvm releases4、验证当前使用的 Flutter 版本&#xff1a; fvm flutter --version5、切换到特定版本的 Flutter fvm use …...

GPT-4o 的“图文合体”是怎么做到的

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

PyTorch教程:如何读写张量与模型参数

本文演示了PyTorch中张量&#xff08;Tensor&#xff09;和模型参数的保存与加载方法&#xff0c;并提供完整的代码示例及输出结果&#xff0c;帮助读者快速掌握数据持久化的核心操作。 1. 保存和加载单个张量 通过torch.save和torch.load可以直接保存和读取张量。 import to…...

MySQL8.0.31安装教程,附pdf资料和压缩包文件

参考资料&#xff1a;黑马程序员 一、下载 点开下面的链接&#xff1a;https://dev.mysql.com/downloads/mysql/ 点击Download 就可以下载对应的安装包了, 安装包如下: 我用夸克网盘分享了「mysql」&#xff0c;链接&#xff1a;https://pan.quark.cn/s/ab7b7acd572b 二、解…...

Linux 系统中对存储设备(/dev/mmcblk、/dev/sd、/dev/nvme)进行分区、格式化或挂载的操作

在 Linux 系统中对存储设备&#xff08;/dev/mmcblk、/dev/sd、/dev/nvme&#xff09;进行分区、格式化或挂载的操作步骤如下&#xff1a; 一、确认设备信息 首先明确要操作的设备名称&#xff08;如 /dev/sdb、/dev/nvme0n1&#xff09;&#xff0c;避免误操作导致数据丢失&a…...