使用融云 CallPlus SDK,一小时实现一款 1V1 视频应用

9 月 21 日,融云直播课 社交泛娱乐出海最短变现路径如何快速实现一款 1V1 视频应用? 欢迎点击小程序报名~

1V1 音视频、远程服务类应用的实现利器——融云 CallPlus SDK 上线! 关注【融云全球互联网通信云】了解更多

作为新一代音视频通话场景化 SDK,融云 CallPlus 完整封装了拨打、接听、挂断等整套呼叫流程,支持一对一及多人音视频通话,功能齐全、体验丝滑,且契合海外用户的交互偏好。

本文将以 Android 端集成为例,分享实战教程:

使用融云 CallPlus SDK,一小时集成 1V1 视频通话能力。

一个 RTC 实时音视频底层零经验开发者,只需 3 个核心 API、4 步 即可轻松实现音视频通话能力。并且,融云提供 Quick Demo 源码供开发者集成参考。


前置条件

创建融云开发者账号

创建融云开发者账号,获取 App Key。

开始之前,需创建融云开发者账号并获取 App Key。在开发者后台,系统会自动为新账号创建一个应用。默认使用国内数据中心,并提供开发环境。如果您已经有融云开发者账号,可以直接创建新应用。

导入 SDK

打开根目录下的 build.gradle(新版 Android studio 为 settings.gradle),Project 视图下,声明融云的 Maven 代码库。

allprojects {repositories {...//融云 maven 仓库地址maven {url "https://maven.rongcloud.cn/repository/maven-releases/"}}
}

添加依赖项

在应用的 build.gradle 中,添加如下远程依赖项。

注意:融云 CallPlus 业务依赖 IM 通道,所以须同时集成 IMLibCore SDK。

dependencies {// 请填写具体的 SDK 版本号,新集成用户建议使用最新版。此处以5.6.2版本为例。implementation 'cn.rongcloud.sdk:im_libcore:5.6.2'  // 即时通讯基础能力库。implementation 'cn.rongcloud.sdk:callplus_lib:1.0.0'// 音视频呼叫能力库(内含 rtc_lib)
}

权限声明

在 AndroidManifest.xml 中声明 SDK 需要的所有权限。

<!-- 允许程序访问网络连接 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 允许程序获取网络信息状态,如当前的网络连接是否有效 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- 允许程序获取当前WiFi接入的状态以及WLAN热点的信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 允许程序访问摄像头进行拍照 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 允许程序录制声音通过手机或耳机的麦克 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 允许程序修改声音设置信息 -->
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<!--允许程序访问电话状态,如通话中收到来自SIM卡的来电时,会将SIM卡通话状态通知给远端用户,所以需要该权限-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

注意:如果开发应用需要支持 Android 6.0(API 级别 23)或更高版本的设备,还需要在 App 用户使用对应功能时(如发起呼叫、接听)请求摄像头(CAMERA)、麦克风(RECORD_AUDIO)权限。

详见 Android 开发者官方文档运行时权限与请求权限的工作流。


正式集成

在着手实现之前,我们需要关注以下几个关键点:

☑ 如何发起通话
☑ 如何接收来电
☑ 通话接通后,双方通话界面如何显示

要想实现通话功能,必须以双端都已经成功连接融云为基础,参考下图所示 1V1 主叫端和被叫端的流程时序图。

主叫端时序图:

被叫端时序图:

初始化连接融云

CallPlus for Android 依赖融云即时通讯客户端 SDK 提供信令通道,故需先对 IMLibCore 进行初始化,建议放到 Application 中。

String appKey = "Your_AppKey"; // example: bos9p5rlcm2ba 创建融云开发者账号,获取 App Key。
InitOption initOption = new InitOption.Builder().build();
RongCoreClient.init(getApplicationContext(), appKey, initOption);

要拨打和接听一对一呼叫或开始多人呼叫,必须先通过 RongCoreClient 的 connect 方法连接融云服务器。

传入用户身份令牌(Token),向融云服务器验证用户身份;连接成功后,使用 RCCallPlusClient.getInstance().init() 方法初始化和配置 CallPlus SDK。

String token = "用户Token";// 您在申请开发者账号后,可以在融云后台北极星位置直接生成用户token
RongCoreClient.connect(token, new IRongCoreCallback.ConnectCallback() {/*** 成功回调* @param userId 当前用户 ID*/@Overridepublic void onSuccess(String userId) {runOnUiThread(new Runnable() {@Overridepublic void run() {//todo 尽管在主线程初始化 RCCallPlusClient 不是必需的,但考虑到代码示例后续对 RCCallPlusClient 的调用都在主线程进行,所以目前选择在主线程进行初始化。//todo 请确保在同一个线程进行 RCCallPlusClient 的初始化、反初始化和使用,以确保操作的一致性。RCCallPlusConfig config = RCCallPlusConfig.Builder.create().build();/*** 初始化并设置通话全局配置,重复调用该方法时SDK内部会重新初始化* @param config    设置通话全局配置* @return 方法调用后同步返回结果,可以在这里得到初始化是否成功*/RCCallPlusResultCode resultCode = RCCallPlusClient.getInstance().init(config);}});}/*** 错误回调* @param errorCode 错误码*/@Overridepublic void onError(IRongCoreEnum.ConnectionErrorCode errorCode) {}/*** 数据库回调.* @param code 数据库打开状态. DATABASE_OPEN_SUCCESS 数据库打开成功; DATABASE_OPEN_ERROR 数据库打开失败*/@Overridepublic void onDatabaseOpened(DatabaseOpenStatus code) {}
});

发起呼叫并设置本地和远端视图

使用 startCall 方法来发起一对一通话。

该方法内部会以异步方式执行,并通过 IRCCallPlusResultListener#onStartCall 回调来获取方法的结果。

在发起通话之前需先设置本地和远端视图,在对端接听视频通话时,本端会自动渲染对端的视图。

使用 setCallPlusResultListener 方法添加通话 API 异步结果回调监听。该监听可以接收 startCall、accept、hangup 等方法的结果回调。

发起呼叫:

  private void startCall(String remoteUserId) {//todo 打开摄像头采集,请提前完成摄像头、麦克风权限的动态申请RCCallPlusClient.getInstance().startCamera();RCCallPlusClient.getInstance().enableMicrophone(true);//设置本端视图setLocalVideoView();//设置对端视图setRemotVideoView(remoteUserId);List<String> userIds = new ArrayList<>();userIds.add(remoteUserId);//todo remoteUserId 为被呼叫的远端用户userIdRCCallPlusType callType = RCCallPlusType.PRIVATE;//PRIVATE: 1V1通话RCCallPlusMediaType mediaType = RCCallPlusMediaType.VIDEO;/*** 开始发起呼叫* 该方法内部为异步执行,结果回调是注册的{@link RCCallPlusClient#setCallPlusResultListener(IRCCallPlusResultListener)} 监听的 {@link IRCCallPlusResultListener#onStartCall(RCCallPlusCode, String, List)}方法<br>*/RCCallPlusClient.getInstance().startCall(userIds, callType, mediaType);}

发起端设置本地视图:

   /*** 设置本地视频渲染视图*/private void setLocalVideoView() {//创建本地视图对象RCCallPlusLocalVideoView localVideoView = new RCCallPlusLocalVideoView(this.getApplicationContext());//FIT: 视频帧通过保持宽高比(可能显示黑色边框)来缩放以适应视图的大小localVideoView.setRenderMode(RCCallPlusRenderMode.FIT);//设置本地视图给  SDKRCCallPlusClient.getInstance().setVideoView(localVideoView);FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);params.gravity = Gravity.CENTER_HORIZONTAL;//在父布局中横向居中显示//将本地视图添加到XML中显示//示例代码中 mLocalVideoViewFrameLayout 为 android.widget.FrameLayout 对象mLocalVideoViewFrameLayout.removeAllViews();mLocalVideoViewFrameLayout.addView(localVideoView, params);}

发起端设置对端视图:

   /*** 发起通话时设置对端视频渲染视图*/private void setRemotVideoView(String remoteUserId) {//创建远端视图对象 remoteUserId为远端用户userIdRCCallPlusRemoteVideoView remoteVideoView = new RCCallPlusRemoteVideoView(remoteUserId, this.getApplicationContext(), false);//FIT: 视频帧通过保持宽高比(可能显示黑色边框)来缩放以适应视图的大小remoteVideoView.setRenderMode(RCCallPlusRenderMode.FIT);//因为远端视图显示在最顶层,为了防止远端视频视图被底部控件遮挡,所以添加如下设置:remoteVideoView.setZOrderOnTop(true);remoteVideoView.setZOrderMediaOverlay(true);List<RCCallPlusRemoteVideoView> remoteVideoViewList = new ArrayList<>(); remoteVideoViewList.add(remoteVideoView);//设置远端视图给SDKRCCallPlusClient.getInstance().setVideoView(remoteVideoViewList);FrameLayout.LayoutParams remoteVideoViewParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);remoteVideoViewParams.gravity = Gravity.CENTER_HORIZONTAL;//将远端视图添加到XML中显示//示例代码中 mRemoteVideoViewFrameLayout 为 android.widget.FrameLayout 对象mRemoteVideoViewFrameLayout.removeAllViews();mRemoteVideoViewFrameLayout.addView(remoteVideoView, remoteVideoViewParams);
}

接收端接听通话并设置本地和远端视图

可选择接听或挂断来电,若要接听电话,请使用 accept 方法;若要挂断来电,请使用 RCCallPlusClient.getInstance().hangup() 方法。

可以通过 RCCallPlusSession#getCallId() 方法获取执行接听和挂断操作所需的 CallId 值。

要接收远端呼叫通知,必须确保已经注册了 IRCCallPlusEventListener,并实现了 onReceivedCall(RCCallPlusSession callSession) 方法。被叫用户通过与融云服务端的连接或者离线推送通知(离线推送 App 必须已集成第三方厂商推送,详见推送 2.0 集成概述)接收来电通知。

使用 setCallPlusEventListener 方法添加通话事件监听,提供来电事件、通话状态、通话记录等事件相关回调。

添加通话事件监听:

RCCallPlusClient.getInstance().setCallPlusEventListener(new IRCCallPlusEventListener() {/*** 用户通过该回调接收到通话呼叫 在这个回调中,可以接听通话** @param callSession   通话实体信息<br>*/@Overridepublic void onReceivedCall(RCCallPlusSession callSession) {RCCallPlusSession currentCallSession = RCCallPlusClient.getInstance().getCurrentCallSession();if (currentCallSession != null && !TextUtils.equals(callSession.getCallId(), currentCallSession.getCallId())) {//可以使用该方法判断出,有正在进行中的通话,又有第二通通话呼入的情况<br>//todo 第二通通话可以直接调用 RCCallPlusClient.getInstance().accept 方法接听,SDK内部会将第一通通话挂断}//todo SDK 的回调均为子线程调用,showDialog() 方法中存在UI操作,所以切换到主线程执行runOnUiThread(new Runnable() {@Overridepublic void run() {//todo 打开摄像头采集,请提前完成摄像头、麦克风权限的动态申请RCCallPlusClient.getInstance().startCamera();RCCallPlusClient.getInstance().enableMicrophone(true);setLocalVideoView();//复用发起通话逻辑中的 设置本地视频渲染视图 方法showDialog(CallPlusActivity.this, "收到通话,是否接听?", "接听", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {acceptCall(callSession);}}, "挂断", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {RCCallPlusClient.getInstance().hangup();}});}});}@Overridepublic void onCallEnded(RCCallPlusSession session, RCCallPlusReason reason) {IRCCallPlusEventListener.super.onCallEnded(session, reason);runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(CallPlusActivity.this,"通话结束,callId: "+session.getCallId() +" 通话结束原因:"+ reason.getValue(), Toast.LENGTH_SHORT).show();}});}/*** 远端用户状态改变监听<br>** @param callId 通话Id<br>* @param userId 用户Id<br>* @param status 该用户当前状态<br>* @param reason 该用户当前状态原因<br>*/@Overridepublic void onRemoteUserStateChanged(String callId, String userId, RCCallPlusUserSessionStatus status, RCCallPlusReason reason) {IRCCallPlusEventListener.super.onRemoteUserStateChanged(callId, userId, status, reason);runOnUiThread(new Runnable() {@Overridepublic void run() {StringBuilder stringBuilder = new StringBuilder("通话 ");stringBuilder.append(callId).append(" 中的远端用户 ").append(userId).append(" 当前状态为 ");switch (status) {case CALLING:stringBuilder.append("呼叫中");break;case INVITED:stringBuilder.append("被邀请中");break;case CONNECTING:stringBuilder.append("已接听,连接中");break;case ON_CALL:stringBuilder.append("通话中");break;case ENDED:stringBuilder.append("通话已结束");break;}Toast.makeText(CallPlusActivity.this, stringBuilder.toString(), Toast.LENGTH_SHORT).show();}});}
});

具体接听通话的方法:

private void acceptCall(RCCallPlusSession callSession) {setRemoteUserVideoView(callSession.getRemoteUserList());/*** 开始接听通话* 该方法内部为异步执行,结果回调是注册的{@link RCCallPlusClient#setCallPlusResultListener(IRCCallPlusResultListener)} 监听的 {@link IRCCallPlusResultListener#onAccept(RCCallPlusCode, String)}方法<br>*/RCCallPlusClient.getInstance().accept(callSession.getCallId());
}

接收端设置本地和远端视图:

/*** 接听方设置远端用户视频渲染视图*/
private void setRemoteUserVideoView(List<RCCallPlusUser> remoteUserList) {List<RCCallPlusRemoteVideoView> remoteVideoViewList = new ArrayList<>();for (RCCallPlusUser callPlusUser : remoteUserList) {RCCallPlusRemoteVideoView remoteVideoView = new RCCallPlusRemoteVideoView(callPlusUser.getUserId(), this.getApplicationContext(), false);//视频帧通过保持宽高比(可能显示黑色边框)来缩放以适应视图的大小remoteVideoView.setRenderMode(RCCallPlusRenderMode.FIT);remoteVideoViewList.add(remoteVideoView);//本示例代码中,因为远端视图显示在最顶层,为了防止远端视频视图被底部控件(视图)遮挡,所以添加如下设置:remoteVideoView.setZOrderOnTop(true);remoteVideoView.setZOrderMediaOverlay(true);FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);params.gravity = Gravity.CENTER_HORIZONTAL;//todo 将每个远端视图(remoteVideoView)添加到XML中显示,远端为多人时,需要添加给多个控件显示,本示例代码仅展示一个远端用户情况mRemoteVideoViewFrameLayout.removeAllViews();mRemoteVideoViewFrameLayout.addView(remoteVideoView, params);}/*** 设置远端用户视频流渲染视图给SDK* 若没有为远端用户设置视频渲染视图,则不会产生该用户的视频流的下行流量*/RCCallPlusClient.getInstance().setVideoView(remoteVideoViewList);
}
private AlertDialog showDialog(Context context, String content, String positiveBtn, final DialogInterface.OnClickListener positiveListener, final String negativeBtn, final DialogInterface.OnClickListener negativeListener) {AlertDialog.Builder builder = new AlertDialog.Builder(context);builder = builder.setMessage(content);builder.setCancelable(false);if (!TextUtils.isEmpty(positiveBtn)) {builder.setPositiveButton(positiveBtn, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {if (positiveListener != null) {positiveListener.onClick(dialog, which);} else {dialog.dismiss();}}});} if (!TextUtils.isEmpty(negativeBtn)) {builder.setNegativeButton(negativeBtn, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {if (negativeListener != null) {negativeListener.onClick(dialog, which);} else {dialog.dismiss();}}});} return builder.show();
}

运行项目发起通话,当被叫端接听并且主叫端能够看到双方视频,说明 1V1 音视频通话核心能力已经实现了,全程仅需 4 个步骤、3 个核心 API。


其他功能

切换前后摄像头

成功打开摄像头后,可以使用 switchCamera 方法切换前后摄像头。

switchCamera 方法是异步调用的,支持通过 IRCCallPlusResultListener 的 onSwitchCamera 回调来获取调用结果。

RCCallPlusClient.getInstance().switchCamera();
RCCallPlusClient.getInstance().setCallPlusResultListener(new IRCCallPlusResultListener() {/*** 切换前后摄像头方法结果回调<br>** @param code 方法请求结果<br>* @param isFrontCamera 当前开启的摄像头是否是前置摄像头<br>*/@Overridepublic void onSwitchCamera(RCCallPlusCode code, boolean isFrontCamera) {IRCCallPlusResultListener.super.onSwitchCamera(code, isFrontCamera);}
});

美颜

融云 SDK 已经接入专业三方美颜服务,三步即可实现美颜功能。

  1. 在应用的 build.gradle 中添加如下远程依赖项。

    implementation 'cn.rongcloud.sdk:fu_beautifier:5.6.2'
    implementation 'androidx.core:core-ktx:1.7.0'

  2. 提供有效的美颜授权文件(感兴趣可联系融云商务详细咨询:131 6185 6839)。
  3. 初始化美颜插件,初始化时请提供有效的美颜授权文件。应用运行期间只调用一次即可,建议在 Application#onCreate 中初始化。

下面代码块中的 authpackNew 即为相关美颜服务的授权文件。

RCRTCFUBeautifierEngine.getInstance().register(getApplicationContext(),null,authpackNew.A(),new FUBeautifierResultCallback() {@Overridepublic void onSuccess() {setBeautyEnable();SetBeautyParameters();}@Overridepublic void onFailed(int code) {}});
private void setBeautyEnable() {// 打开美颜开关后设置的美颜效果才会生效;关闭开关美颜会失效。RCRTCFUBeautifierEngine.getInstance().setBeautyEnable(true, new FUBeautifierResultCallback() {@Overridepublic void onSuccess() {}@Overridepublic void onFailed(int code) {}});
}
// 设置美颜参数
private void SetBeautyParameters() {RCRTCFUBeautifierEngine.getInstance().setBlurIntensity(6); 范围[0-6]RCRTCFUBeautifierEngine.getInstance().setColorIntensity(2); // 范围 [0-2]RCRTCFUBeautifierEngine.getInstance().setRedIntensity(2);// 范围 [0-2]RCRTCFUBeautifierEngine.getInstance().setSharpenIntensity(1);// 范围 [0-1]RCRTCFUBeautifierEngine.getInstance().setEyeBrightIntensity(1); // 范围 [0-1]RCRTCFUBeautifierEngine.getInstance().setToothIntensity(1);// 范围 [0-1]RCRTCFUBeautifierEngine.getInstance().setRemovePouchIntensity(1);// 范围 [0-1]RCRTCFUBeautifierEngine.getInstance().setRemoveLawPatternIntensity(1);// 范围 [0-1]
}

在业务开发集成、上线运营等全过程中,融云都将提供全流程一站式技术服务支持,开发者可提交工单与融云工程师交流。欢迎来电咨询:131 6185 6839


最后,callback 一下融云 CallPlus SDK 的核心优势:

完整封装:提供完整的呼叫功能方案,包括连接、呼叫、接听、拒接、挂断、呼叫状态通知等。

集成便捷:接口设计贴近业务且简洁明了,结合 Quick Demo 源码,开发者只需使用 3 个核心接口,一小时即可实现音视频通话核心功能。

场景全面:支持 iOS、Android、Web 等平台,可以满足陌生人社交、在线招聘、远程医疗、线上咨询、售后客服等多种单人和多人通话场景使用。

服务稳定: 100% 可靠必达的音视频呼叫信令能力,保证连接安全可靠;音频弱网抗丢包 80%,视频弱网抗丢包 60%,并有 3A 算法,保证通话清晰稳定。

周边完善:提供业务场景所需的丰富高级功能,包括内容审核、云端录制、高级美颜等,让开发者的业务开展无忧且高效。

性价比高:目前月功能费仅为 1500 元/月,含 200,000 分钟免费时长。场景灵活度高,不限音视频,视频最高分辨率可支持 2K+;真正省心透明,支持 RTC 与 IM 服务单独采购,且不单独收取呼叫信令费用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/130596.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Python和mysql开发的看图猜成语微信小程序(源码+数据库+程序配置说明书+程序使用说明书)

一、项目简介 本项目是一套基于Python和mysql开发的看图猜成语微信小程序&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Python学习者。 包含&#xff1a;项目源码、项目文档、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都…

2022年全国研究生数学建模竞赛华为杯A题移动场景超分辨定位问题求解全过程文档及程序

2022年全国研究生数学建模竞赛华为杯 A题 移动场景超分辨定位问题 原题再现&#xff1a; 在日常家庭生活中&#xff0c;人们可能需要花费大量时间去寻找随意摆放在家中某些角落里的小物品。但如果给某些重要物品贴上电路标签&#xff0c;再利用诸如扫地机器人的全屋覆盖能力&…

前端实现页面通过canvas添加全屏水印

写在前面&#xff0c;博主是个在北京打拼的码农&#xff0c;从事前端工作5年了&#xff0c;做过十多个大大小小不同类型的项目&#xff0c;最近心血来潮在这儿写点东西&#xff0c;欢迎大家多多指教。 对于文章中出现的任何错误请大家批评指出&#xff0c;一定及时修改。有任何…

视频直播点播平台EasyDSS如何单独保存录像计划文件?具体如何操作呢?

视频推拉流EasyDSS视频直播点播平台&#xff0c;集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体&#xff0c;可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务。 有用户反馈&#xff1a;在视频直播点播平台EasyDSS中设置了片段形…

【数据结构--二叉树】合并二叉树

/*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/struct TreeNode* mergeTrees(struct TreeNode* root1, struct TreeNode* root2){if(root1NULL&&root2NULL)//两个二叉树都…

华为云云耀云服务器L实例评测|Linux系统之安装Tomcat

华为云云耀云服务器L实例评测&#xff5c;Linux系统之安装Tomcat 一、云耀云服务器L实例介绍1.1 云耀云服务器L实例简介1.2 云耀云服务器L实例特点 二、Tomcat介绍2.1 Tomcat简介2.2 Tomcat特点 三、本次实践介绍3.1 本次实践简介3.2 本次环境规划 四、购买云耀云服务器L实例4.…

risc-v dv源代码分析

地址为 GitHub - chipsalliance/riscv-dv: Random instruction generator for RISC-V processor verificationRandom instruction generator for RISC-V processor verification - GitHub - chipsalliance/riscv-dv: Random instruction generator for RISC-V processor verif…

Windows驱动开发(一)

1. 引言 很难为术语 “驱动程序”提供一个精确的定义。 就最基本的意义而言&#xff0c;驱动程序是一个软件组件&#xff0c;可让操作系统和设备彼此通信。 例如&#xff0c;假设应用程序需要从设备中读取某些数据。 应用程序会调用由操作系统实现的函数&#xff0c;操作系统…

Windows下Git Bash的基本使用

创建版本库 git init 初始化完成后&#xff0c;会在目录下创建一个.git的隐藏目录&#xff0c;用来存放项目信息。 、 添加文件到版本库 在项目目录下新建文件readme.txt&#xff0c;内容为 Git is a version control system Git is a free software This is my first Try …

MySQL知识笔记——初级基础(实施工程师和DBA工作笔记)

老生长谈&#xff0c;MySQL具有开源、支持多语言、性能好、安全性高的特点&#xff0c;广受业界欢迎。 在数据爆炸式增长的年代&#xff0c;掌握一种数据库能够更好的提升自己的业务能力&#xff08;实施工程师&#xff09;。 此系列将会记录我学习和进阶SQL路上的知识&#xf…

Haproxy搭建Web群集

常见的Web集群调度器分为软件和硬件 软件通常使用开源的LVS、Haproxy、Nginx。 * LVS 性能最好&#xff0c;但是搭建相对复杂 * Nginx的upstream模块支持群集功能&#xff0c;但是对群集节点健康检查功能不强&#xff0c;高并发性能没有Haproxy好。 硬件一般使用比较多的是F5、…

postman连接websocket 测试(v8.5.1)

1. postman v8.5版本 以上支持 websocket。 2. 选择websocket请求模块File - New... 3. 输入请求地址, ws:// 控制台输出: 2023-09-12 15:29:23.039 INFO 11592 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet di…

sql注入之高权限注入和文件读写

死在山野的风里&#xff0c;活在自由的梦里 sql注入之高权限注入 高权限注入1.多个网站共享mysql服务器2.MySQL 权限介绍3.注入流程查询所有数据库名称查询表名对应的字段名查询数据 文件读写1.文件读写注入的原理2.文件读写注入的条件3.读取文件4.写入文件 高权限注入 在数据…

学习SpringMvc第三战-利用SpringMvc实现CRUD

目录 一.前期环境搭建 1.替换pom.xml的内容 2.导入配置文件(小编上传资源) 3.修改xml文件 4.点击创建自动生成代码 5.写一个类用于处理页面跳转 二.正式启动SpringMVC的CRUD 1.建立接口&#xff0c;调用自动生成的接口 2.构建分页代码 2.1书写BookMapper.xml中分页的方…

12个最受欢迎的3D打印机械臂【开源|DIY|套件】

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 机器人手臂的用途各不相同&#xff0c;但大多数都能够执行拾取和放置任务&#xff0c;而有些则配备用于 CNC 工作、激光雕刻&#xff0c;甚至 3D 打印。 机械臂具有广泛的应用和各个领域&#xff0c;从执行精密手术和进行工…

Kafka3.0.0版本——消费者(分区的分配以及再平衡)

目录 一、分区的分配以及再平衡1.1、消费者分区及消费者组的概述1.2、如何确定哪个consumer来消费哪个partition的数据1.3、消费者分区分配策略 一、分区的分配以及再平衡 1.1、消费者分区及消费者组的概述 一个consumer group中有多个consumer组成&#xff0c;一个 topic有多…

go语言基本操作---六

并发编程 并行&#xff1a;指在同一时刻&#xff0c;有多条指令在多个处理器上同时执行。 并发&#xff1a;指在同一时刻只能有一条指令执行&#xff0c;但是多个进程指令被快速的轮换执行&#xff0c;使得在宏观上具有多个进程同时执行的效果&#xff0c;但在微观上并不是同时…

python机器人编程——用python实现一个写字机器人

目录 一、前言二、整体框架2.1 系统构成2.2 硬件介绍2.2.1主要组成部分2.2.2机械结构2.2.3驱动及控制主板PS电机驱动原理简介: 2.2.4其余部分 2.3 机器人python程序框架2.3.1通信服务模块2.3.2消息处理模块2.3.3轨迹解析模块2.3.4机械臂逆解模块2.3.5写字板模块 三、机械臂的建…

浅谈基于LoRa通信技术的建筑能耗监测系统及模块

安科瑞 华楠 摘要&#xff1a;本文提出采用LoRa通信技术开发设计建筑能耗监测系统的建议&#xff0c;通过系统&#xff0c;该系统功能完善、界面友好、通信稳定&#xff0c;在建筑能耗监测领域中有较高的推广价值。 关键词&#xff1a;LoRa通信&#xff1b;建筑能耗&#xff…

63、SpringBoot---定制 RestTemplate--消息转化器、拦截器

★ 定制RestTemplate 如要对RestTemplate进行自定义设置&#xff0c;Spring Boot也提供了两种主要方式&#xff1a;▲ 局部式&#xff1a;在调用RestTemplateBuilder构建RestTemplate之前&#xff0c;先调用RestTemplateBuilder的方法对其定制&#xff0c;通过这种方式设置的R…