现在最火的.NET跨平台UI框架莫过于Avalonia了。Avalonia 基于.NET Core,因此它可以运行在任何支持.NET Core的平台上。之前基于CPF跨平台UI框架写过一个视频聊天的demo,而现在看来Avalonia是大势所趋,于是,我再写一个Avalonia版本的Demo来供大家参考,它可以在Windows和Linux(包括国产OS,如银河麒麟、统信UOS)上运行。
下图是视频聊天Demo的Avalonia客户端在国产统信UOS上的运行的截图:
一.功能介绍
客户端登录成功后,运行的主界面如下图所示:
1. 视频聊天
(1)每个登录的用户都可向其他任意在线用户发送视频聊天请求。
(2)当收到来自其他在线用户的视频聊天邀请时,可接受或拒绝对方的请求。
(3)当接受其他在线用户的视频聊天邀请时,即可开启视频聊天。
2. 远程桌面
(1)每个登录的用户都可向其他任意在线用户发送远程桌面请求;当对方未响应时,可主动取消远程桌面请求。
(2)当收到来自其他在线用户请求控制桌面时,可接受或拒绝对方的请求。
(3)当发送方收到其他在线用户同意控制其电脑时,即可开启远程桌面连接。
(4)被控端和主控端都可主动断开远程桌面连接。
二.开发环境
1.开发工具:
Visual Studio 2022
2. 开发框架:
.NET Core 3.1
3.开发语言:
C#
4.其它框架:
Avalonia UI 框架(版本:0.10.22)、OMCS 语音视频框架 (版本:8.0)
注:建议 Avalonia 使用0.10.*的版本,精简而且很稳定,而最新的11.0的版本太庞大了。
三.具体实现
下面我们讲一下Demo中核心的代码实现,大家从文末下载源码并对照着源码看,会更清楚些。
1.自定义消息类型 InformationTypes
public static class InformationTypes{/// <summary>/// 视频请求 0/// </summary>public const int VideoRequest = 0;/// <summary>/// 回复视频请求的结果 1/// </summary>public const int VideoResult = 1;/// <summary>/// 通知对方 挂断 视频连接 2/// </summary>public const int CloseVideo = 2;/// <summary>/// 通知好友 网络原因,导致 视频中断 3/// </summary>public const int NetReasonCloseVideo = 3;/// <summary>/// 通知对方(忙线中) 挂断 视频连接 4/// </summary>public const int BusyLine = 4;/// <summary>/// 远程桌面请求 5/// </summary>public const int DesktopRequest = 5;/// <summary>/// 回复远程桌面请求的结果 6/// </summary>public const int DesktopResult = 6;/// <summary>/// 主动取消远程桌面请求 7/// </summary>public const int CancelDesktop = 7;/// <summary>/// 对方(主人端)主动断开远程桌面 8/// </summary>public const int OwnerCloseDesktop = 8;/// <summary>/// 客人端断开远程桌面连接 9/// </summary>public const int GuestCloseDesktop = 9;}
2. 发送视频请求
(1)当发起视频聊天时,将显示视频聊天窗口
/// <summary>/// 打开视频通话窗口/// </summary>/// <param name="destID">对方ID</param>/// <param name="isWorking">false表示主动发起视频通话邀请</param>internal void OpenVideoChat(string destID,bool isWorking){if (!this.VideoInvokeVerdict(destID)){return;}App.Multimedia.OutputAudio = true;VideoChatWindow videoChatWindow = new VideoChatWindow(destID, isWorking);videoChatWindow.EndTheCalled += VideoChatWindow_EndTheCalled;objectManager.Add(destID, videoChatWindow);videoChatWindow.Show();}
(2)连接自己的摄像头
public VideoChatWindow(string destID,bool isWorking){this.DestID = destID;this.IsWorking = isWorking;InitializeComponent();//连接自己的摄像头this.selfCamera.Core.DisplayVideoParameters = true;this.selfCamera.Core.VideoDrawMode = VideoDrawMode.ScaleToFill;this.selfCamera.BeginConnect(MainWindow.CurrentID);this.Title = this.title.Text = this.RepeatedCallTip(false);this.timer = new System.Timers.Timer();this.timer.Interval = 1000;this.timer.Elapsed += Timer_Elapsed;if (IsWorking){ this.BeginConnect();}}
(3)发送视频通话请求
protected override void OnInitialized(){base.OnInitialized(); this.SetWindowStats();if (!this.IsWorking){//向对方发起视频通话邀请VideoController.Singleton.SendMessage(this.DestID, InformationTypes.VideoRequest, null);}}
3. 回复对方视频请求
(1)当收到对方的视频聊天邀请时,将显示视频邀请窗口
(2)发送回复视频聊天请求消息
protected override void OnClosed(EventArgs e){base.OnClosed(e);if (this.EndTheCalled != null){this.EndTheCalled(this.DestID);}if (this.NotifyOther){ //回复对方的视频通话请求byte[] bytes = BitConverter.GetBytes(replyResult);VideoController.Singleton.SendMessage(this.DestID, InformationTypes.VideoResult, bytes);}if (this.replyResult){VideoController.Singleton.OpenVideoChat(DestID,true);}}
4. 收到对方视频请求的回复
/// <summary>/// 视频通话,收到对方回复/// </summary> internal void TargerReply(string destID, CommunicationStateType type){ICommunicationAid aid = this.objectManager.Get(destID);if(aid == null){return;} switch (type){case CommunicationStateType.Agree:VideoChatWindow videoChatWindow = (VideoChatWindow)aid;videoChatWindow.BeginConnect();break;case CommunicationStateType.Reject: aid.CloseWindow(false);break;case CommunicationStateType.HangUp: aid.CloseWindow(false);break;default:break;}}
当对方回复同意时,将连接到对方的麦克风和摄像头,开始视频聊天会话:
/// <summary>/// 连接对方设备/// </summary>internal void BeginConnect(){UiSafeInvoker.ActionOnUI(() =>{this.IsWorking = true;this.Title = this.title.Text = this.RepeatedCallTip(false);this.startTime = DateTime.Now;this.timer.Start();this.otherCamera.Core.DisplayVideoParameters = true;this.otherCamera.Core.VideoDrawMode = VideoDrawMode.ScaleToFill;this.otherCamera.Core.ConnectEnded += DynamicCameraConnector_ConnectEnded;this.otherCamera.Core.Disconnected += DynamicCameraConnector_Disconnected;this.microphoneConnector.ConnectEnded += MicrophoneConnector_ConnectEnded;this.microphoneConnector.Disconnected += MicrophoneConnector_Disconnected;this.otherCamera.BeginConnect(this.DestID);this.microphoneConnector.BeginConnect(this.DestID);this.NotifyOther = true;});}
5. 实现远程桌面
远程桌面的请求/应答逻辑几乎与视频聊天请求/应答逻辑是一模一样的。这里就不再罗列响应的代码了。
(1)当收到对方的远程桌面控制请求时,将显示请求窗口。
(2)当同意对方的控制请求时,对方就可以控制请求方的电脑了。
四.源码下载
.NetCore服务端 + Avalonia客户端:VideoChatMini.Avalonia.rar
在Windows上部署运行服务端和客户端很容易,大家也都很熟悉了。下面讲一下如何在Linux上部署运行这个视频聊天程序的服务端和客户端。
在Linux上部署运行说明
在部署之前,需要在linux服务端和客户端上分别安装 .Net core 3.1版本,命令行安装命令如下:
yum install dotnet-sdk-3.1
检查版本安装情况
dotnet --version
运行:
(1)在CentOS上启动VideoChatMini.ServerNetcore服务端:
拷贝Oraycn.VideoChatMini.ServerNetcore项目下的Debug文件夹,到CentOS操作系统上,打开Debug -> netcoreapp3.1目录 ,在目录下打开终端,执行以下命令启动服务端
dotnet Oraycn.VideoChatMini.ServerNetcore.dll
(2)在麒麟或统信UOS、Ubuntu上运行VideoChatMini.ClientAvalonia客户端:
拷贝Oraycn.VideoChatMini.ClientAvalonia项目下的Debug文件夹,到麒麟或统信UOS、Ubuntu操作系统上,打开Debug -> netcoreapp3.1目录 ,在目录下打开终端,执行以下命令启动客户端
dotnet Oraycn.VideoChatMini.ClientAvalonia.dll
命令执行成功后,就会出现之前截图的客户端主界面。
Avalonia 支持在X64和ARM64架构的Linux上运行,Demo的运行目录下放的是X64架构的so,如果需要ARM64架构的so,可留下邮箱获取。