技术教程 | 如何实现1v1音视频通话(含源码)
今天,给大家讲一下怎么实现1v1音视频通话,以下是教程内容:
开发环境
开发环境要求如下:
环境要求 | 说明 |
---|---|
JDK 版本 | 1.8.0 及以上版本 |
Android API 版本 | API 21、Android Studio 5.0 及以上版本 |
CPU架构 | ARM 64、ARMV7 |
IDE | Android Studio |
其他 | 依赖 Androidx,不支持 support 库。 |
注意事项
1 对 1 娱乐社交场景方案的呼叫能力基于云信呼叫组件,
技术原理
一对一通话功能页面结构如下:
页面 | 描述 |
---|---|
CallActivity | 呼叫页&&通话页容器,默认加载CallFragment,在呼叫接通后根据音视频类型加载InTheAudioCallFragment或者InTheVideoCallFragment |
CallFragment | 呼叫页UI,包括主叫与被叫 |
InTheAudioCallFragment | 音频通话页UI,包括主叫与被叫 |
InTheVideoCallFragment | 视频通话页UI,包括主叫与被叫 |
音视频通话的时序图如下图所示。
用户A呼叫组件AG2服务器信令服务器呼叫组件B业务服务器用户B呼叫计费alt[一方挂断电话][出现欠费]请求校验是否可以发起呼叫返回校验结果,分配ChannelName、uid等信息(可选)A发起呼叫邀请呼叫组件发起呼叫邀请A邀请B的信令A邀请BB接听B接听B加入RTCB接听的信令A加入RTCB接听发送用户A 加入房间的抄送发送用户B 加入房间的抄送开始计费通话中客户端向业务服务器发送计费心跳(可选)发送用户离开房间的抄送停止计费发送通话话单出现欠费,销毁房间通话结束通话结束通话结束通话结束用户A呼叫组件AG2服务器信令服务器呼叫组件B业务服务器用户B
步骤1 集成呼叫组件 SDK
1 对 1 娱乐社交场景方案的呼叫能力基于云信呼叫组件来进行实现。
-
在工程根部目录的
build.gradle
文件中添加如下代码。allprojects {repositories {//...mavenCentral()//...} }
-
在主工程
build.gradle
文件中添加如下代码,引入呼叫组件。// 若出现 More than one file was found with OS independent path 'lib/arm64-v8a/libc++_shared.so'. // 可以在主 module 的 build.gradle 文件中 android 闭包内追加如下 packageOptions 配置 android{//......packagingOptions {pickFirst 'lib/arm64-v8a/libc++_shared.so'pickFirst 'lib/armeabi-v7a/libc++_shared.so'} }dependencies {// 集成呼叫组件 https://doc.yunxin.163.com/nertccallkit/docs/DMzOTI3NTA?platform=androidimplementation 'com.netease.yunxin.kit.call:call-ui:x.x.x' }
步骤2 初始化 IM SDK
在 Application
的 onCreate
中,调用init方法进行初始化。
示例代码
public class SampleApplication extends Application {@Overridepublic void onCreate() {super.onCreate();NIMClient.init(this, null, options());}// 如果返回值为 null,则全部使用默认参数。private SDKOptions options() {SDKOptions options = new SDKOptions();//此处仅设置appkey,其他设置请自行参考信令的初始化文档:https://doc.yunxin.163.com/docs/DA5MjI4NDY/zY0NDU2OTE?platformId=80002options.appKey = AppConstants.APP_KEY;return options;}}
步骤3 登录 IM
调用login方法登录 IM。
本文以实现静态 Token 登录为例,动态 Token 登录以及自动登录的实现
public class LoginActivity extends Activity {public void doLogin() {LoginInfo info = new LoginInfo(); RequestCallback<LoginInfo> callback =new RequestCallback<LoginInfo>() {@Overridepublic void onSuccess(LoginInfo param) {LogUtil.i(TAG, "login success");// your code}@Overridepublic void onFailed(int code) {if (code == 302) {LogUtil.i(TAG, "账号密码错误");// your code} else {// your code}}@Overridepublic void onException(Throwable exception) {// your code}};//执行手动登录NIMClient.getService(AuthService.class).login(info).setCallback(callback);}
}
步骤4 初始化呼叫组件
IM 登录成功后,初始化呼叫组件。
示例代码(✉LTT936可以获完整源码)
在IM登录成功之后,初始化呼叫组件if (ProcessUtils.isMainProcess()){initCallKit();}private void initCallKit() {CallKitUIOptions options = new CallKitUIOptions.Builder()// 必要:音视频通话 sdk appKey,用于通话中使用.rtcAppKey(AppConstants.APP_KEY)// 必要:当前用户 AccId.currentUserAccId(UserInfoManager.getSelfImAccid())// 此处为 收到来电时展示的 notification 相关配置,如图标,提示语等。.notificationConfigFetcher(invitedInfo -> new CallKitNotificationConfig(R.mipmap.ic_launcher))// 收到被叫时若 app 在后台,在恢复到前台时是否自动唤起被叫页面,默认为 true.resumeBGInvitation(true).rtcTokenService(new TokenService() {@Overridepublic void getToken(long uid, RequestCallback<String> callback) {HttpService.requestRtcToken(uid).subscribe(new ResourceSingleObserver<BaseResponse>() {@Overridepublic void onSuccess(BaseResponse response) {LogUtil.d("getToken", "response:" + response);if (response.isSuccessful()) {callback.onSuccess((String) response.data);} else {callback.onFailed(response.code);}}@Overridepublic void onError(Throwable e) {LogUtil.e("getToken", "e:" + e);callback.onException(e);}});}}) // 自己实现的 token 请求方法.rtcSdkOption(new NERtcOption())// 呼叫组件初始化 rtc 范围,true-全局初始化,false-每次通话进行初始化以及销毁// 全局初始化有助于更快进入首帧页面,当结合其他组件使用时存在rtc初始化冲突可设置false.rtcInitScope(true)// 配置音频呼叫页.p2pAudioActivity(CallActivity.class)//配置视频呼叫页.p2pVideoActivity(CallActivity.class).build();
// 若重复初始化会销毁之前的初始化实例,重新初始化PstnCallKitOptions pstnCallKitOptions = new PstnCallKitOptions.Builder(options).timeOutMillisecond(CallConfig.CALL_TOTAL_WAIT_TIMEOUT).transOutMillisecond(CallConfig.CALL_PSTN_WAIT_MILLISECONDS).build();PstnUIHelper.init(getApplicationContext(), pstnCallKitOptions);}
步骤5 实现呼叫功能
示例代码
// 唤起呼叫页面 CallParam param = CallParam.createSingleCallParam(ChannelType.VIDEO.getValue(), UserInfoManager.getSelfImAccid(), userModel.imAccid, extraInfo.toString());CallKitUI.startSingleCall(context, param);//开始呼叫 doCall(new JoinChannelCallBack() {@Overridepublic void onJoinChannel(ChannelFullInfo channelFullInfo) {LogUtil.i(TAG, "rtcCall onJoinChannel");callback.onSuccess(channelFullInfo);}@Overridepublic void onJoinFail(String msg, int code) {LogUtil.e(TAG, "rtcCall,onJoinFail msg:" + msg + ",code:" + code);callback.onError(code, msg);}});
步骤6 实现计费逻辑
// 可以在通话接通成功之后,每1分钟上报一次信息给您的APP应用服务器,做计费处理Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {// 将本次通话信息上报给您的APP服务器}},1000,60*1000,TimeUnit.MILLISECONDS);
步骤7 实现挂断功能
示例代码
doHangup(new RequestCallbackWrapper<Void>() {@Overridepublic void onResult(int code, Void result, Throwable exception) {LogUtil.i(TAG, "rtcHangup,code:" + code + ",exception:" + exception);callback.onSuccess(code);}
});
步骤8 实现接听功能
示例代码
doAccept(new JoinChannelCallBack() {@Overridepublic void onJoinChannel(ChannelFullInfo channelFullInfo) {LogUtil.i(TAG, "rtcAccept onJoinChannel");}@Overridepublic void onJoinFail(String msg, int code) {LogUtil.e(TAG, "rtcAccept,onJoinFail msg:" + msg + ",code:" + code);}
});
步骤9 添加呼叫监听
示例代码
private final NERtcCallDelegate neRtcCallDelegate = new NERtcCallDelegate() {@Overridepublic void onFirstVideoFrameDecoded(@Nullable String userId, int width, int height) {super.onFirstVideoFrameDecoded(userId, width, height);// 视频首帧回调}@Overridepublic void onVideoMuted(String userId, boolean isMuted) {super.onVideoMuted(userId, isMuted);// 对端视频mute的回调}@Overridepublic void onUserEnter(@Nullable String userId) {super.onUserEnter(userId);LogUtil.i(TAG, "onUserEnter,userId:" + userId);// 用户进入通话回调}@Overridepublic void onCallEnd(@Nullable String userId) {super.onCallEnd(userId);LogUtil.i(TAG, "onCallEnd,userId:" + userId);// 通话结束回调}@Overridepublic void onRejectByUserId(@Nullable String userId) {super.onRejectByUserId(userId);LogUtil.i(TAG, "onRejectByUserId,userId:" + userId);// 拒绝通话的回调}@Overridepublic void onUserBusy(@Nullable String userId) {super.onUserBusy(userId);LogUtil.i(TAG, "onUserBusy,userId:" + userId);// 对方占线的回调}@Overridepublic void onCancelByUserId(@Nullable String userId) {super.onCancelByUserId(userId);LogUtil.i(TAG, "onCancelByUserId,userId:" + userId);// 对方取消呼叫的回调}@Overridepublic void timeOut() {LogUtil.i(TAG, "timeOut");// 呼叫超时的回调}};NERTCVideoCall.sharedInstance().addDelegate(neRtcCallDelegate);
如果您需要移除呼叫监听,请参考如下示例代码:
NERTCVideoCall.sharedInstance().removeDelegate(neRtcCallDelegate);
步骤10 实现小窗功能
示例代码
java // 重写CommonCallActivity的provideUIConfig方法@Nullable@Overrideprotected P2PUIConfig provideUIConfig(@Nullable CallParam callParam) {ALog.d(TAG, new ParameterMap("provideUIConfig").append("param", callParam).toValue());return new P2PUIConfig.Builder().foregroundNotificationConfig(new CallKitNotificationConfig(R.mipmap.ic_launcher))// 设置小窗功能.enableFloatingWindow(true)// 设置通话页面切到Home页时自动小窗功能.enableAutoFloatingWindowWhenHome(true).enableVirtualBlur(true).build();}// 切换到小窗模式doShowFloatingWindow();
最终的呈现效果是这样的,大家速速体验!更详细的源码可以戳底部名片呀~~👇👇
相关文章:
技术教程 | 如何实现1v1音视频通话(含源码)
今天,给大家讲一下怎么实现1v1音视频通话,以下是教程内容: 开发环境 开发环境要求如下: 环境要求说明JDK 版本1.8.0 及以上版本Android API 版本API 21、Android Studio 5.0 及以上版本CPU架构ARM 64、ARMV7IDEAndroid Studio其…...
mysql实时同步到es
测试了多个方案同步,最终选择oceanu产品,底层基于Flink cdc 1、实时性能够保证,binlog量很大时也不产生延迟 2、配置SQL即可完成,操作上简单 下面示例mysql的100张分表实时同步到es,优化备注等文本字段的like查询 创…...
Linux-ubuntu系统移植之Uboot启动流程
Linux-ubuntu系统移植之Uboot启动流程 一,Uboot启动流程1.Uboot的两阶段1.1.第一阶段1.11.硬件初始化1.12.复制 U-Boot 到 RAM1.13.跳转到第二阶段 1.2.第二阶段1.21.C 语言环境初始化1.22. 硬件设备初始化1.23. 加载环境变量1.24. 显示启动信息1.25. 等待用户输入&…...
《Operating System Concepts》阅读笔记:p62-p75
《Operating System Concepts》学习第 10 天,p62-p75 总结,总计 14 页。 一、技术总结 1. system call (1) 定义 The primary interface between processes and the operating system, providing a means to invoke services made available by th…...
【Java场景题】MySQL死锁排查
大家好,今天XiXi给大家分享一个MySQL死锁排查的实验,文章主要有: 通过show engine innodb status,查看最近一次死锁信息开启innodb_print_all_deadlocks,在错误日志中能够记录所有死锁信息通过解析binlog日志定位死锁…...
JSON格式,C语言自己实现,以及直接调用库函数(一)
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。以下为你提供不同场景下常见的 JSON 格式示例。 1. 简单对象 JSON 对象是由键值对组成,用花括号 {} 包裹&…...
leetcode刷题第十三天——二叉树Ⅲ
本次刷题顺序是按照卡尔的代码随想录中给出的顺序 翻转二叉树 226. 翻转二叉树 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*//*总体思路就是,对于每一个结点&…...
spring boot知识点5
1.如何你有俩套配置环境,运行时如何选择 如果有俩套配置环境,则需要三个yml application.yml 用于配置你用那个配置环境 application-dev.yml 用于开发配置环境 application-prod.yml 用于发布配置环境 spring:profiles:active: prod # 指定当前激…...
bboss v7.3.5来袭!新增异地灾备机制和Kerberos认证机制,助力企业数据安全
ETL & 流批一体化框架 bboss v7.3.5 发布,多源输出插件增加为特定输出插件设置记录过滤功能;Elasticsearch 客户端新增异地双中心灾备机制,提升框架高可用性;Elasticsearch client 和 http 微服务框架增加对 Kerberos 认证支持…...
Android自带的省电模式主要做什么呢?
Android自带的省电模式主要做什么呢? 省电模式支持的策略 LOCATION 灭屏后开启GPS待机省电模式 VIBRATION 关闭触摸震动和来电震动 ANIMATION 关闭动画 FULL_BACKUP 全备份 KEYVALUE_BACKUP 键值备份 NETWORK_FIREWALL 网络防火墙,限制 Doze …...
tp6上传文件大小超过了最大值+验证文件上传大小和格式函数
问题: 最近用tp6的文件上传方法上传文件时报文件过大错误。如下所示: $file $this->request->file(file);{"code": 1,"msg": "上传文件大小超过了最大值!","data": {"code": 1,&q…...
将RocketMQ集成到了Spring Boot项目中,实现站内信功能
1. 添加依赖 首先,在pom.xml中添加RocketMQ的依赖: <dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifac…...
Spring Boot文件上传
5.3.1文件上传 开发Web应用时,文件上传是很常见的一个需求浏览器通过表单形式将文件以流的形式传递给服务器,服务器再对上传的数据解析处理。下面我们通过一个案例讲解如何使用SpringBoot实现文件上传,具体步骤如下。 1.编写文件上传的表单…...
动态规划算法
动态规划算法模板 public class DynamicProgramming {public int solve(int n, int[] nums) {// Step 1: 初始化 dp 数组,dp[i] 表示从0到i的最优解int[] dp new int[n 1]; // Step 2: 设置初始条件,通常是dp数组的第一个元素dp[0] 0; // 假设从第0个…...
Python中常见库 PyTorch和Pydantic 讲解
PyTorch 简介 PyTorch 是一个开源的深度学习框架,由 Facebook 的 AI 研究团队开发。它提供了丰富的工具和库,用于构建和训练各种深度学习模型,如卷积神经网络(CNN)、循环神经网络(RNN)及其变体&…...
74. 搜索二维矩阵(LeetCode 热题 100)
题目来源; 74. 搜索二维矩阵 - 力扣(LeetCode) 题目内容: 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &am…...
高防服务器的适用场景有哪些?
高防服务器作为具有着较高防御能力的网络设备,可以抵御DDOS和CC等常见的网络攻击类型,保障企业服务的连续性和稳定性,那高防服务器的适用场景有哪些呢? 对于大型的网站和电商平台来说,高流量的用户访问和数据信息让它们…...
HTTP与网络安全
一、HTTPS和HTTP有怎样的区别呢?HTTPS HTTP SSL/TLS(SSL或者TLS) HTTP:应用层 SSL/TLS:协议中间层 TCP:传输层 IP:网络层 HTTPS 是安全的HTTP,他的安全是由SSL或者TLS来决定的&a…...
UE地编材质世界对齐纹理旋转
帖子地址 https://forums.unrealengine.com/t/how-to-rotate-a-world-aligned-texture/32532/4世界对齐纹理本身不能改 自己创建了个函数 把世界对齐纹理的内容赋值粘贴 在纹理偏移里给值 不要局限0-1 给值给大一点...
SpringBoot使用Nacos进行application.yml配置管理
Nacos是阿里巴巴开源的一个微服务配置管理和服务发现的解决方案。它提供了动态服务发现、配置管理和 服务管理平台。Nacos的核心功能包括服务发现、配置管理和动态服务管理,使得微服务架构下的服务治理 变得简单高效。 Nacos的设计基于服务注册与发现、配置管理、动…...
JavaScript中的symbol类型的意义和使用
JavaScript 中的Symbol类型是 ES6(ECMAScript 2015)引入的一种原始数据类型,它表示独一无二的值。下面详细介绍 Symbol 的意义和使用方法。 意义 1. 避免属性名冲突 在 JavaScript 中,对象的属性名通常是字符串。当多个模块或者…...
C++ 设计模式-状态模式
火箭状态模式,涵盖发射、多级分离、入轨、返航、紧急状态等流程,以及状态间的转换逻辑: 状态设计 状态列表: IdleState(待机)PreparingState(准备)LaunchingState(发射中)FirstStageSeparatingState(一级分离)SecondStageSeparatingState(二级分离)ThirdStageSep…...
verilog基础知识
一,Verilog和VHDL区别 全世界高层次数字系统设计领域中,应用Verilog和VHDL的比率是80%和20%;这两种语言都是用于数字电路系统设计的硬件描述语言, 而且都已经是 IEEE 的标准。 VHDL 是美国军方组织开发的,VHDL1987年成为标准;Verilog 是由一个公司的私有财产转化而来,…...
14.8 Auto-GPT 自主智能体设计解密:构建具备长期记忆的智能决策系统
Auto-GPT 自主智能体设计解密:构建具备长期记忆的智能决策系统 关键词:Auto-GPT 架构设计、自主智能体开发、LangChain Agents、长期记忆系统、工具链编排 1. 自主智能体的核心架构设计 Auto-GPT 系统架构图解: #mermaid-svg-NuDU1eo6sXqhA6Ve {font-family:"trebuch…...
ubuntu安装docker docker/DockerHub 国内镜像源/加速列表【持续更新】
ubuntu安装docker & docker镜像代理【持续更新】 在Ubuntu上安装Docker,你可以选择两种主要方法:从Ubuntu的仓库安装,或者使用Docker的官方仓库安装。下面我会详细解释这两种方法。 方法一:从Ubuntu的仓库安装Docker 这种方…...
模拟实现分布式文件存储
Q1:如何解决海量数据存的下的问题 传统做法是在单机存储。但是随着数据变多,会遇到存储瓶颈。 单机纵向扩展:内存不够加内存,磁盘不够加磁盘。有上限限制,不能无限制加下去。 多机横向扩展:采用多台机器存储&#x…...
HW面试经验分享 | 北京蓝中研判岗
目录: 所面试的公司介绍 面试官的问题: 1、面试官先就是很常态化的让我做了一个自我介绍 2、自我介绍不错,听你讲熟悉TOP10漏洞,可以讲下自己熟悉哪些方面吗? 3、sql注入原理可以讲下吗? 4、sql注入绕WAF有…...
HarmonyOS学习第3天: 环境搭建开启鸿蒙开发新世界
一、引言 在数字化时代,操作系统作为连接用户与硬件设备的桥梁,其重要性不言而喻。HarmonyOS 作为华为公司推出的面向全场景的分布式操作系统,以其创新的理念和卓越的性能,正逐渐在全球范围内崭露头角。它打破了设备之间的界限&a…...
基于STM32与BD623x的电机控制实战——从零搭建无人机/机器人驱动系统
系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 一、为什么选择这两个芯片?1.1 STM32微控制器1.2 ROHM BD623x电机驱动 二、核心控制原理详解2.1 H桥驱动奥…...
【react18】如何使用useReducer和useContext来实现一个todoList功能
重点知识点就是使用useReducer来攻坚小型的公共状态管理,useImmerReducer来实现数据的不可变 实现效果 实现代码 项目工程结构 App.js文件 import logo from "./logo.svg"; import "./App.css"; import TodoLists from "./comps/TodoLi…...
Java多线程三:补充知识
精心整理了最新的面试资料,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 Lambda表达式 简介: 希腊字母表中排序第十一位的字母,英语名称为Lambda避免匿名内部类定义过多其实质属于函数式编程的概念 为什么要使用lam…...
go WEB框架
推荐选型 https://chat.deepseek.com/a/chat/s/e6061607-8f33-4768-a5f0-8970cb1ffefd echo github:https://github.com/labstack/echo wiki:https://echo.labstack.com/docs/quick-start block:https://blog.csdn.net/qq_38105536/artic…...
【Python爬虫(27)】探索数据可视化的魔法世界
【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取ÿ…...
渲染 101 支持 3ds Max 的渲染器及其优势
在 3ds Max 创作流程里,渲染环节对最终成果的呈现效果起着决定性作用,渲染 101 云渲染平台则为 3ds Max 用户提供了全面且高效的渲染解决方案。 支持的渲染器 V-Ray 渲染器 在 3ds Max 中应用广泛,具备全局光照、光线追踪技术,…...
在 Java 中使用 `if` 语句实现双重判定
关于在 Java 中使用 if 语句实现双重判定,并使用 Eclipse 和 JUnit4 进行单元测试的详细介绍: --- ### 一、双重判定的实现 **双重判定**指在 if 语句中通过逻辑运算符组合两个条件。常用方式: - **逻辑与 &&**:两个条件…...
Ollama 安装
Ollama 支持多种操作系统,包括 macOS、Windows、Linux 以及通过 Docker 容器运行。 Ollama 对硬件要求不高,旨在让用户能够轻松地在本地运行、管理和与大型语言模型进行交互。 CPU:多核处理器(推荐 4 核或以上)。GPU…...
Docker Swarm 内置的集群编排
在现代容器化应用中,容器编排(Container Orchestration)是至关重要的,它负责自动化容器的部署、扩展、负载均衡和管理。Docker Swarm 是 Docker 提供的原生集群管理和容器编排工具,允许用户通过 Docker CLI 在多个 Doc…...
AF3 _build_query_to_hit_index_mapping函数解读
AlphaFold3 中templates模块的_build_query_to_hit_index_mapping函数是将原始查询序列(original_query_sequence)中的索引与hit 序列(hit_sequence)中的索引进行映射。 在蛋白质序列比对(如 HHsearch)中,hit 是与查询序列部分匹配的区域。由于存在缺口(-)和部分比对…...
Windows 中的启动项如何打开?管理电脑启动程序的三种方法
在日常使用电脑时,我们经常会发现一些应用程序在开机时自动启动,这不仅会拖慢系统的启动速度,还可能占用不必要的系统资源。幸运的是,通过几个简单的步骤,你可以轻松管理这些开机自启的应用程序。接下来,我…...
科普:“git“与“github“
Git与GitHub的关系可以理解为:Git是一种软件工具,而GitHub则是一个在线平台,它们是“一家子”。二者的关联最直接体现在你通过Git在GitHub仓库中clone软件包到你的机器中来。 具体来说: 一、Git 定义:Git是一个开源的…...
module ‘cv2.dnn‘ has no attribute ‘DictValue‘解决办法
module ‘cv2.dnn‘ has no attribute ‘DictValue‘解决办法 pip install opencv-python4.7.0.72 -i https://pypi.tuna.tsinghua.edu.cn/simple 测试: python -c"import cv2"...
国产编辑器EverEdit - 语法着色及嵌入式多语言着色
1 文档-着色及语法相关 1.1 应用场景 在编辑代码文件或脚本文件过程中,如果对语法着色、模式等文件进行了修改,需要立即生效时,可以通过文档-高级功能下的重新加载功能,立即生效相关配置。 1.2 使用方法 1.2.1 重新加载着色 着…...
设计模式教程:解释器模式(Interpreter Pattern)
1. 什么是解释器模式? 解释器模式(Interpreter Pattern)是一种行为型设计模式,通常用于处理语言(例如数学表达式、SQL查询等)中的语法和解释。该模式定义了一个文法,并通过解释器类来解释文法中…...
Three.js 快速入门教程【六】相机控件 OrbitControls
系列文章目录 Three.js 快速入门教程【一】开启你的 3D Web 开发之旅 Three.js 快速入门教程【二】透视投影相机 Three.js 快速入门教程【三】渲染器 Three.js 快速入门教程【四】三维坐标系 Three.js 快速入门教程【五】动画渲染循环 Three.js 快速入门教程【六】相机控件 Or…...
【git】合并多个提交记录
1.说明 有时候因为某些小修改会导致代码多了很多不必要的提交,如果希望合并这些commit记录,我们可以使用rebase或者reset命令完成合并 2.rebase 这种方式是通过变基操作完成的,它适用于已经push到远程的情况,当我们变基好了之后…...
题海拾贝:【枚举】P2010 [NOIP 2016 普及组] 回文日期
Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路! 我的博客:<但凡. 我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞,关注! 1、题…...
SQL Server 链接服务器 MySQL 详细步骤
目录 前言 一、准备工作 1. 确认需求 2. 获取权限 二、安装必要的驱动程序和工具 1.下载并安装MySQL ODBC驱动: 2.安装 SQL Server 和 MySQL 的管理工具: 三、配置 SQL Server 以连接到MySQL 1.执行创建链接服务器的T-SQL语句: 2.配…...
Java集合框架之List接口详解
目录 一、List接口概述 二、List接口常见实现类 三、List接口特有方法: 1.元素操作 2. 查找元素位置 3. 子列表与不可变列表 四、List特有迭代器:ListIterator 1.特有的迭代方式 2.ListIterator接口中的常用方法: ⑴.void add(E e):在光标位置插入元素。(会移动…...
【大语言模型_4】源码编译vllm框架cpu版
背景: 通过官方提供的pip install vllm安装的vllm框架不支持cpu加载模型。因此需要本地编译。 系统环境 操作系统:欧拉2203 python版本:3.10 编译步骤 一、安装gcc/g/cmake 1、下载源码:https://github.com/vllm-project/vllm 安…...
城市地质安全专题连载⑦ | 加强国土空间规划管控,规避城市地质安全风险
作者 | 徐海洋 在国土空间规划中,地质调查扮演着先导性和基础性的角色。它如同一把无形的尺子,衡量着每一寸土地的开发潜力与安全边界,不仅为城市规划提供了科学依据,还在规避地质安全风险、优化资源配置方面发挥着关键作用。然而…...