Tizen Web应用程序中的Wi-Fi Direct和套接字
简介现在的Web应用程序只通过利用Web API是不允许使用Wi-Fi Direct。 然而,在Tizen有一个解决方法可以充分利用Wi-Fi Direct。Web应用程序可以有一个在后台运行的服务应用程序(本机)。 服务应用程序可以运行本地代码,并使用原生API,并同时与该web应用程序进行通信。 通过使用与Web应用程序连同的服务应用程序,我们可以对Web环境提供原生API。信息端口可以管理发送到服务程序的请求和对Web程序的响应,这个功能可以实现web程序和原生程序之间的沟通。 然而,有两个应用程序是让令人烦恼的,因为这两个应用程序从一开始就是相互分离的程序,在应用程序管理器中也是作为两个不同的应用程序存在。 感谢Tizen打包系统,我们可以把服务应用程序放入到web应用程序里创建一个软件包,这个软件包被称为混合程序。为了使一切更简单,我们已经实现了服务应用程序来管理Wi-Fi Direct。 我们还创建了JavaScript库,使与服务端的沟通更容易。本文的第一部分介绍了原生部分:[*]如何在Tizen上使用WiFI Direct
[*]如何在设备之间设置套接字通信
本机部分 web 库提出了允许 web 和本机层之间进行通信的消息端口。WiFi DirectWiFi Direct是基于点对点体系结构,使两个或更多的设备,无需任何接入点就可以进行直接通信的技术。
Wi-Fi Direct通信直接的沟通,如发送消息,两个 Tizen 设备之间是可能的,例如使用 Wi-Fi Direct和套接字。 Wi-Fi Direct API 和套接字 API 都可适用于Tizen,但只能在原生 Tizen 上。Wi-Fi Direct API 允许开发人员启用、 禁用 WiFi Direct、 扫描设备、 配对、 更改无线网络配置等等。 可能采取的行动的完整列表将详细描述,也适用于这里:Wi-Fi Direct 连接。
WifiDirectDeviceWi-Fi Direct API 的主要重点是围绕 WifiDirectDevice 类。 这个类的对象管理整个Tizen 设备上 Wi-Fi Direct连接。 它提供大部分关键的功能,它需要启动和停止Wi-Fi适配器。 为了获得的 WifiDirectDevice 实例,开发人员必须调用 WifiDirectDeviceManager::GetWifiDirectDeviceN() 函数获得Wi-Fi Direct管理器的指针。 WifiDirectDevice 提供了以下功能:
[*]结果 Activate(void)
在Tizen设备上激活 Wi-fi Direct。
[*]bool IsActivated (void) const
检查是否 Wi-fi Direct 已激活。
[*]bool IsDiscoverable (void) const
检查该设备是否可被其他使用 Wi-Fi Direct的设备检测到。
[*]result AddWifiDirectDeviceListener (IWifiDirectDeviceListener &listener)
设置将接受所有Wi-Fi Direct通知的监听器。 每当发生重要事件时,来自 IWifiDirectDeviceListener 的一个合适的回调函数将会运行,例如 OnWifiDirectDeviceActivated 或 OnWifiDirectScanCompletedN。
[*]result Scan (void)
WiFi direct被激活后,此函数扫描其他 Wi-Fi Direct激活的设备。 这也包括 Android 设备。 作为 OnWifiDirectScanCompletedN 函数中的参数返回所有可以连接的设备。
[*]result Connect (const WifiDirectDeviceInfo &remoteDeviceInfo)
将设备连接到 WifiDirectDeviceInfo 对象所定义的远程设备。 WifiDirectDeviceInfo 对象可以从 OnWifiDirectScanCompletedN 函数获得,这个函数返回 WifiDirectDeviceInfo 对象的列表。 Tizen 设备和 Android 的设备之间的连接也是可能的。 连接函数立即返回函数结果,但这一结果只定义如果连接的过程已成功启动了或不。 在 OnWifiDirectConnected 回调函数返回实际的连接结果。
[*]result CancelConnect (void)
停止当前操作的两个设备之间连接。
[*]result CancelScan (void)
停止当前的扫描进程,为其他设备。
[*]result CreateAutonomousGroup (void)
创建Wi-Fi Direct组并成为组的所有者。 多个设备连接到一个需要创建组。 创建组的设备将成为所有者,其他设备可以作为客户机加入。
[*]result Disconnect (const WifiDirectDeviceInfo &peerDeviceInfo)
从远程设备断开连接。
[*]result LeaveGroup (void)
由调用组所有者调用来销毁组并断开所有客户端。 一个客户端调用来从已经加入的组内断开连接
[*]result Deactivate (void)
停用 WifiDirect。
[*]result RemoveWifiDirectDeviceListener (IWifiDirectDeviceListener &listener)
删除已绑定 WiFi 侦听器。
[*]Tizen::Base::Collection::IList * GetGroupClientInfoListN (void) const
返回连接到设备上的所有客户端的列表。 这个函数只被组所有者调用才工作。 如果被客户端调用,则返回null。
[*]WifiDirectDeviceInfo * GetGroupOwnerInfoN (void) const
返回有关用户组所有者的信息。 如果组的所有者调用将返回 null。
[*]WifiDirectGroupInfo * GetGroupSettingInfoN (void) const
返回有关连接到的当前组的设备的信息。
[*]WifiDirectDeviceInfo * GetLocalDeviceInfoN (void) const
返回设备WifiDirect的有关信息,例如设备名称或者IP地址。
[*]WifiRadioChannel GetOperatingChannel (void) const
返回当前的操作通道。
[*]WifiWpsConfigurationMode GetWpsConfigurationModePreference (void) const
返回当前的配置模式。
[*]result SetGroupSettingInfo (const WifiDirectGroupInfo &groupSettingInfo)
设置Wi-Fi Direct设置,例如连接到某一组的设备的最大数量。
[*]result SetLocalDeviceName (const Tizen::Base::String &name)
设置设备名称
[*]result SetWpsConfigurationModePreference (WifiWpsConfigurationMode mode)
设置 Wps 配置模式
[*]
正如你所看到的大多数函数返回的结果。 这是一个枚举类型,它定义了所调用函数的输出。 例如,如果函数执行失败它可以是E_FAILURE,如果函数执行成功,它可以是E_SUCCESS。 结果也可能是 E_INVALID_OPERATION,如果被调用的函数不被允许在当前的 Wi-Fi Direct状态被调用。 例如 Wi-Fi Direct处于不活动状态时,所以调用 SetLocalDeviceName,WiFi 处于活动状态时将导致返回 E_INVALID_OPERATION 结果只能执行设置设备名称。这是WifiDirectDevice对象如何工作以及它有什么可能性的基本概念。 关于 WifiDirectDevice 类的详细信息,请参阅文档。
Wi-Fi Direct样例现在你已经熟悉了TIzen上的Wi-Fi Direct API,这里是一个怎么连接一个设备到其他设备的例子。 首先,我们需要获得一个 WifiDirectDevice 实例:<font size="4">std::unique_ptr<Tizen::Net::Wifi::WifiDirectDevice> __pWifiDirectLocalDevice;
__pWifiDirectLocalDevice.reset(WifiDirectDeviceManager::GetWifiDirectDeviceN());</font>现在我们想要在 WifiDirect 发生的事情的所有通知。 我们需要设置 Wi-fi Direct 监听器。 Wi-Fi Direct监听器可以是任何继承自 Tizen::Net::Wifi::IWifiDirectDeviceListener,并实现其所有的函数。<font size="4">__pWifiDirectLocalDevice->AddWifiDirectDeviceListener(*this);</font>通过 *this作为参数将设置一个对象,这个对象来自一个被调用的作为Wi-Fi Direct监听器。下一步激活 Wi-fi Direct 是非常简单:<font size="4">__pWifiDirectLocalDevice->Activate();</font>为了连接到其他设备,我们需要扫描可用的设备,并选择其中之一。<font size="4">__pWifiDirectLocalDevice->Scan();</font>在调用扫描后,我们需要等待结果。 可用的设备列表将作为 OnWifiDirectScanCompletedN 回调函数中的参数传递。 如果我们想要连接到列表中的第一个设备,我们需要从列表中获取 WifiDirectDeviceInfo 对象。<font size="4">void
OnWifiDirectScanCompletedN(WifiDirectDeviceId localDeviceId, Tizen::Base::Collection::IList *pWifiDirectDeviceInfoList, result r)
{
WifiDirectDeviceInfo* pDeviceInfo = static_cast<WifiDirectDeviceInfo*>( __pDeviceInfoList->GetAt(0));
}</font>正如你可以看到 pDeviceInfo 作为第一个在扫描列表中的设备。 现在,我们有一个 WifiDirectDeviceInfo 对象我们可以连接到远程设备上,只是,如下所示。<font size="4">__pWifiDirectLocalDevice->Connect(*pDeviceInfo);</font>连接的结果将公布在 OnWifiDirectConnected 回调函数。套接字套接字允许通过创建两个端点之间的连接,允许网络上设备之间进行通信。在Tizen上他们可以使用套接字 API 。 更详细的说明,以及文档,可以在这里找到。现在我们将聚焦于如果在我们的库使用套接字。首先,我们创建了连接管理器:<font size="4">__pNetConnection = new NetConnection();
r = __pNetConnection->Construct(accountId);
if (r != E_SUCCESS) {
AppLog("Failed to construct NetConnection"); return false;
}
r = __pNetConnection->AddNetConnectionListener(*(INetConnectionEventListener*) this);
if (r != E_SUCCESS) {
AppLog("Failed to add listener to NetConnection"); return false;
}
r = __pNetConnection->Start();
if (r != E_SUCCESS) {
AppLog("Failed to start NetConnection"); return false;
}</font>也是一个类,用于管理网络连接,表示运行时的会话。在那之后,我们初始化套接字:<font size="4">__pUdpSocket = new Socket();
r = __pUdpSocket->Construct(*__pNetConnection, NET_SOCKET_AF_IPV4, NET_SOCKET_TYPE_DATAGRAM, NET_SOCKET_PROTOCOL_UDP);
TryReturn(r == E_SUCCESS, r, "[%s] Sokcet Construct Failed", GetErrorMessage(r));
r = __pUdpSocket->SetSockOpt(NET_SOCKET_SOL_SOCKET, NET_SOCKET_SO_BROADCAST, 1);
TryReturn(r == E_SUCCESS, r, "[%s] SetSockOpt Failed", GetErrorMessage(r));
r = __pUdpSocket->AddSocketListener(*(ISocketEventListener*) this);
TryReturn(r == E_SUCCESS, r, "[%s] AddSocketListener Failed", GetErrorMessage(r));
r = __pUdpSocket->AsyncSelectByListener(NET_SOCKET_EVENT_READ | NET_SOCKET_EVENT_WRITE | NET_SOCKET_EVENT_CLOSE);
TryReturn(r == E_SUCCESS, r, "[%s] AsyncSelectByListener Failed", GetErrorMessage(r));
r = __pUdpSocket->Bind(localEndPoint);
TryReturn(r == E_SUCCESS, r, "[%s] UDP socket Bind Failed", GetErrorMessage(r));</font>现在,套接字都已初始化,我们可以在设备之间发送消息。 有两种方法做到这一点: 通过发送广播消息,我们的 WiFi 网络中的所有设备都将收到:<font size="4">Ip4Address broadcastAddress("255.255.255.255");
NetEndPoint recvEndPoint(broadcastAddress, DEFAULT_CHAT_PORT);
r = __pUdpSocket->SendTo(*pBuffer, recvEndPoint);</font>或者,消息发送到指定的ip 地址:<font size="4">Ip4Address ipAddress(ip);
NetEndPoint recvEndPoint(broadcastAddress, DEFAULT_CHAT_PORT);
r = __pUdpSocket->SendTo(*pBuffer, recvEndPoint);</font>
当收到一条消息,回调函数被调用:<font size="4">void
HybridWifiDirectServiceApp::OnSocketReadyToReceive(Tizen::Net::Sockets::Socket& socket)
{
unsigned long arg = 0;
result r = socket.Ioctl(NET_SOCKET_FIONREAD, arg);
if (r != E_SUCCESS) {
AppLog("OnSocketReadyToReceive() | Socket ioctl for read is failed | %ls", GetErrorMessage(r));
return;
}
Ip4Address ip4Address("0");
ByteBuffer buffer;
NetEndPoint netEndPoint(ip4Address, 0);
buffer.Construct(arg);
r = socket.ReceiveFrom(buffer, netEndPoint);
if (r != E_SUCCESS) { return;
}
IpAddress* pIpAddress = netEndPoint.GetAddress();
if (pIpAddress->GetNetAddressFamily() != NET_AF_IPV4) {
AppLog("OnSocketReadyToReceive() | IpAddress is not IPV4");
return;
}
String ipAddress = pIpAddress->ToString();
// Check if socket is initialized.
if (__pNetConnection == null) {
return;
}
// Skip my address
const IpAddress* localAddress = __pNetConnection->GetNetConnectionInfo()->GetLocalAddress();
if (localAddress->ToString() == ipAddress) {
return;
}
buffer.Flip();
String message;
r = StringUtil::Utf8ToString((char*) buffer.GetPointer(), message);
if (r != E_SUCCESS) {
AppLog("OnSocketReadyToReceive() | %ls", GetErrorMessage(r));
return;
}
AppLog("Broadcast message %ls from %ls", message.GetPointer(), ipAddress.GetPointer());
return;
}</font>
上面的代码演示如何创建一个套接字连接、 发送消息和接收它。 这些都是只是基本的套接字连接。 我们只被想表明我们的方法,并且描述如何轻松地使用套接字进行设备之间的连接和通信。然后提出原生 API,并描述如何使用它,我们可以集中在抛出API给Web 环境。 为了做到这一点,我们将创建消息端口用于本机 web 通信的混合应用程序。混合应用程序构建一个混合应用程序时,我们必须在 Tizen IDE 中创建至少两个项目。 在此示例中,第一个项目是为 HybridWifiDirectService 应用程序。 第二个项目将是一个 web 应用程序,这个web应用使用这个服务,包括 JavaScript 库,与服务程序进行通信。 让我们打开您的 IDE 内的 HybridWifiDirectService 项目创建一个空的 Web 项目和命名,例如,"HybridWifiDirectWeb"。
请参阅下面的图片:
https://developer.tizen.org/sites/default/files/users/user-2059/wifidirect_1.png
IDE 中的原生和Web 项目现在,我们必须将这些项目连接在一起。 要这样做,请打开 HybridWifiDirectWeb 项目属性,并转到项目的引用屏幕。 在右边是可以与当前连接的其他项目的名单。 选择HybridWifiDirectService 项目,然后单击确定。 现在在项目资源管理器视图中,您将看到额外的文本 [与 HybridWifiDirectWeb] 下一步的 HybridWifiDirectService 项目名称。https://developer.tizen.org/sites/default/files/users/user-2059/wifidirect_2.png
与原生连接而混合的 web 项目接下来,生成 HybridWifiDirectWeb 项目,你会得到 HybridWifiDirectWeb.wgt 打包。 该软件包包含 web 和本机应用程序。 当在设备上安装此软件包时,必须确认两个应用程序的权限。 然而,当运行应用程序时,只有web 应用程序将自动启动,服务亦要手动运行。 这项服务与web应用程序有着相同的应用程序id。你可以阅读更多关于混合应用程序中的文档在这里和这里。启动服务应用程序从 web 应用程序启动服务应用程序并且不能手动启动,你可以包含文章附件里的tizen.hybrid.js库。 让我们看看它是如何管理这一任务。tizen.hybrid.js 库具有 startService 功能,在开始时正在运行的应用程序,并检查是否我们服务应用程序是这些应用程序之一。 它是通过执行 tizen.application.getAppscontext 函数。<font size="4">try {
// Get applications contexts for applications that are currently running.
tizen.application.getAppsContext(_onGetAppsContextSuccess, _onGetAppsContextError);
} catch (e) {
console.error('Error when trying to get running applications contexts');
}</font>如果服务已启动,则它只是执行回调函数 (如果提供)。 如果不是,它试图通过运行 launchService 函数启动服务。 首先,我们获取服务的标识,只是启动它通过执行 tizen.application.launch 功能。 如果它失败意味着我们可能没有给定id的服务应用程序。 然而,如果我们正确地配置混合应用程序,它工作应该没有任何问题。<font size="4">var serviceId = lib.getServiceId(),
serviceName = lib.getServiceName();
// Running service not found. Trying to launch it.
try {
tizen.application.launch(serviceId, _onLaunchSuccess, _onLaunchError);
} catch (e) {
console.error('Error when launching service "' + serviceName + '" (' + serviceId + ')');
}</font>使用消息端口进行通信当谈论到消息端口,我们要清楚区分本地和远程端口是什么。 本地端口就是那个给定应用程序用来从另一个应用程序接收消息的端口。 该应用程序是用于与远程应用程序进行通信的远程端口。 它更好地在这里的图所示。 本机和 web 应用程序有两个消息端口本地和远程。在我们混合包里,启动通信的是web程序。 我们通过创建本地和远程端口开始。 创建消息端口的代码位于 tizen.hybrid.js库的startMessagePort函数。 两个端口有可以识别它们的名字 (一个应用程序可以有多个本地和远程端口)。<font size="4">var self = this,
localMessagePortName = lib.getLocalMessagePortName(),
serviceId = lib.getServiceId(),
servicePortName = lib.getServicePortName();
try {
_localMessagePort = tizen.messageport.requestLocalMessagePort(localMessagePortName);
_localMessagePortWatchId = _localMessagePort.addMessagePortListener(function (data, remote) {
if (lib.onReceive && typeof lib.onReceive === 'function') {
lib.onReceive(data, remote);
} else {
_onReceive(data, remote);
}
});
console.log('Local message port received');
} catch (e) {
_startMessagePortCallback({code: 'CANT_GET_LOCAL_MESSAGE_PORT'});
console.error('Error when requesting local messageport (' + e.name + ')');
}
try {
_remoteMessagePort = tizen.messageport.requestRemoteMessagePort(serviceId, servicePortName);
console.log('Remote message port received');
_startMessagePortCallback();
} catch (e) {
_startMessagePortCallback({code: 'CANT_GET_REMOTE_MESSAGE_PORT'});
console.error('Error when requesting remote messageport (' + e.name + ')');
}</font>如你所见,创建的本地消息端口之后,, 我们使用 addMessagePortListener 函数收听从另一个应用程序发送来的消息。 现在有两个消息端口,我们可以开始将消息发送到远程应用程序。 由tizen.hybrid.js 内部的本地化的发送函数代码负责。<font size="4">var _send = function (request, data) {
_remoteMessagePort.sendMessage([
{ key: 'request', value: request },
{ key: 'data', value: JSON.stringify(data) }
], _localMessagePort);
};</font>我们在远程端口执行sendMessage函数,传递的数据作为第一个参数,本地端口作为第二个参数。 原生服务应用程序上的本地消息端口会知道它应该响应哪个端口。负责管理消息端口在本机应用程序中的代码位于 HybridMessagePort.cpp 文件。Wi-Fi Direct库Wi-Fi Direct库由两部分组成: 服务和网络。 大部分的服务代码被本地化位于 HybridWifiDirectService.cpp 文件的HybridWifiDirectServiceApp 类。 来自web应用程序的任何请求被消息端口转移到 HybridWifiDirectServiceApp 类。 函数被服务应用执行,响应被发送回 web 应用。您的 web 应用程序包含了 tizen.hybrid.js 和 tizen.wifidirect.js 文件,你得到额外的 wifidirect 对象作为 tizen 对象的属性。 Tizen.wifidirect 对象包含您将需要在 web 应用程序使用 Wi-Fi Direct的所有功能。当 web 应用程序要求执行某些功能时,响应并不是立即返回。 相反,当给定的请求被处理时,我们必须传递一个将被执行的回调函数,响应被返回给web应用程序。 请参阅下面的示例:<font size="4">tizen.wifidirect.init(function (error, result) {
// If error occurred when initializing WifiDirect
if (error) {
alert('Error occurred when initializing WifiDirect');
}
});</font>我们可以把 Wi-fi Direct 功能分成三组,在函数执行后,会发生什么:
[*]函数调用回调只是为了处理错误(setGroupSettingsInfo、setDeviceName、setWpsConfigurationModePreference、sendBroadcast、sendMessage)——他们设置一些值,调用回调来通知是否操作成功。
[*]函数调用回调来处理错误和返回操作(isActivated、isDiscoverable、getGroupClientInfoList、getGroupOwnerInfo)的结果——他们获得一些值,服务端不需要等待,并且还通知是否操作成功。
[*]函数调用回调来处理错误并等待响应,事件侦听器可以处理这些响应 (更多关于后来) (init,activate、 deactivate、 scan、 cancelScan,connect,cancelConnect、disconnect、 createGroup、 leaveGroup、 initSocket)-此函数的每个功能都有其相应的完成操作时将被执行的事件,例如激活函数等待激活事件。
侦听一个事件,会在未来使用 addEventListener 函数,像在下面的示例。<font size="4">tizen.wifidirect.activate(function (error) {
if (error) {
alert('Error occurred when trying to activate WifiDirect');
}
});
tizen.wifidirect.addEventListener('activated', function (error) {
if (error) {
alert('Error occurred when trying to activate WifiDirect');
} else {
// WifiDirect has been activated
}
});</font>回调函数传递给 addEventListener 还可以收到一些数据,例如在 scanCompleted 事件,采用有源器件作为第二个参数的列表。<font size="4">tizen.wifidirect.scan(function (error) {
if (error) {
alert('Error occurred when trying to scan network');
}
});
tizen.wifidirect.addEventListener('scanCompleted', function (error, devices) {
if (error) {
alert('Error occurred when trying to scan network');
} else {
// Do something with the list of devices
console.log(devices);
}
});</font>处理请求web 库执行函数时,它就会跳转去HybridWifiDirectServiceApp 类中OnUserEventReceivedN 侦听器。 请求是一个整数,数据是 JSON 字符串。 请求列表在HybridWifiDirectService.h文件的请求结构里,并在tizen.wifidirect.js文件的_Request对象里。 在OnUserEventReceivedN 函数内部,我们采取的行动依赖于传递到切换状态的请求类型(requestId)。<font size="4">switch (requestId) {
case Request::INIT:
InitWifiDirect();
break;
case Request::ACTIVATE:
SendResponse(Response::ACTIVATE, __pWifiDirectLocalDevice->Activate(), null);
break;
case Request::DEACTIVATE:
SendResponse(Response::DEACTIVATE, __pWifiDirectLocalDevice->Deactivate(), null);
break;
case Request::IS_ACTIVATED:
SendResponse(Response::IS_ACTIVATED, E_SUCCESS, new JsonBool(__pWifiDirectLocalDevice->IsActivated()));
break;
case Request::IS_DISCOVERABLE:
SendResponse(Response::IS_DISCOVERABLE, E_SUCCESS, new JsonBool(__pWifiDirectLocalDevice->IsDiscoverable()));
break;
/* ... */
}</font>一些请求只在switch-case语句块被处理,其他的则被指定的函数处理。 操作被处理后,响应必须被发回web库。 通过运行SendResponse函数来实现。它采用响应代码作为第一个参数。 响应代码是定义在 HybridWifiDirectService.h 文件中的响应结构和在 tizen.wifidirect.js 文件中的 _Response 对象中定义的代码之一。第二个参数是 Tizen 结果代码。 各操作可以产生不同的结果代码,但是当操作成功时,结果码为E_SUCCESS。 在Tizen的文件,每一个函数附近你可以找到它所产生的错误的详细信息。SendResponse 函数的第三个参数是一个 JSON 对象,包含响应数据。用法总结起来,web应用程序要使用 Wi-fi Direct 库可以按照下列步骤操作:
[*]添加HybridWifiDirectService 项目到 IDE
[*]创建 web 应用程序项目
[*]通过连接服务应用程序和Web应用程序来创建混合应用程序。
[*]添加 tizen.hybrid.js 和 tizen.wifidirect.js 文件到您的 web 应用程序。
[*]调用 tizen.wifidirect.init() 函数,并等到 Wi-Fi Direct初始化。
现在,您已准备好要使用 Web API 的功能。示例应用程序本文附带的示例应用程序是一个简单的聊天程序。 下面的图片显示应用程序的屏幕截图。https://developer.tizen.org/sites/default/files/users/user-2059/screenshot.png
示例应用程序的屏幕截图很重要 !现在,应用程序无法在模拟器上运行,因为缺乏 Wi-Fi Direct的支持。 你必须在物理设备上运行应用程序。很重要 !要使用 Wi-Fi Direct,你首先要关掉Wi-Fi无线上网。 我们计划在未来的库版本增加对激活和停止Wi-Fi的支持。Web 应用程序需要两个特权:
[*]http://tizen.org/privilege/application.info
[*]http://tizen.org/privilege/application.launch
在应用程序的顶部,你有两个按钮。 通过单击创建聊天室,您创建 Wi-fi Direct 组,任何带有 Wi-fi Direct的 设备都可以连接到这个组。 下一页按钮显示聊天室的可显示的 Wi-fi Direct 的组的列表,并允许连接到其中之一。下一个选项是输入字段,显示 Wi-fi Direct 设备名称。 只有Wi-Fi Direct处于活动状态时它才是激活的。 更改设备的名称不会导致永远地改变。 只要 Wi-Fi 直接处于活动状态它就仍然存在,。接下来两个字段是聊天区域和带发送按钮的消息区域。 消息将会广播到所有连接到给定聊天室的设备。应用程序的核心是聊天对象,它包含所有函数。 第一个运行的函数是init。 它启动应用程序 UI 和 WifiDirect。 在那之后,它会检查 Wi-fi Direct 是否处于活动状态。当创建 Wi-Fi Direct组或显示组的列表时,我们检查 Wi-fi Direct 是否处于活动状态。 如果不是,我们试着激活它并继续执行给定函数。 序艾旭端口和 Wi-Fi Direct是异步的,我们必须考虑到这点。 单击“创建聊天室”按钮后,我们设置_creating标志设置为true,然后单击“显示聊天室”后,我们设置_joining标志设置为true。<font size="4">$create.on('click', function () {
_creating = true;
if (_isActivated) {
chat.createChatRoom();
} else {
chat.activate();
}
});
$show.on('click', function () {
_joining = true;
if (_isActivated) {
chat.showChatRooms();
} else {
chat.activate();
}
});</font>
如果点击创建或显示按钮时,Wi-Fi Direct未激活,我们使用这些标志。 在激活的事件,我们检查的这两个标志的设置,并继续由单击给定按钮引起的操作。<font size="4">tizen.wifidirect.addEventListener('activated', function (error) {
chat.loading(false);
if (error) {
alert('Error occurred when trying to activate WifiDirect');
return;
}
_isActivated = true;
chat.getDeviceName();
if (_creating) {
chat.createChatRoom();
} else if (_joining) {
chat.showChatRooms();
}
});</font>我们也有标志,确定是否我们是聊天室 / Wi-Fi Direct组的所有者或只是一个客户端。 该_groupOwner标志用于确定组所有者,_isConnected标志被两个组所有者和用户所使用,以通知连接已经建立。最后一个重要的变量是 _connectedClients,其中包含当前组客户的数目。 每当客户端连接到组中时,它会增加;当客户端断开连接时,它就会增加。 当客户的数量为 0 时,这意味着该组被销毁,所以我们可以刷新 UI。 当客户端连接到组,我们通过调用 tizen.wifidirect.initSocet 函数启动套接字连接。 它允许连接的设备和组内的其它设备之间的通信。<font size="4">tizen.wifidirect.addEventListener('connected', function (error, deviceInfo) {
chat.loading(false);
if (error) {
alert('Error occurred when trying to connect');
_joining = false;
return;
}
if (_groupOwner) {
_connectedClients++;
} else {
_isConnected = true;
chat.updateUI();
tizen.wifidirect.initSocket(function (error) {
if (error) {
alert('Error occurred when initializing socket connection');
}
});
}
});
tizen.wifidirect.addEventListener('disconnected', function (error, deviceInfo) {
chat.loading(false);
if (error) {
alert('Error occurred when trying to disconnect');
return;
}
if (_groupOwner) {
_connectedClients--;
if (_connectedClients === 0) {
_isConnected = false;
_groupOwner = false;
chat.updateUI();
}
} else {
_isConnected = false;
chat.updateUI();
}
});</font>值得一提的最后一件事是通信本身。 我们使用广播 (tizen.wifidirect.sendBoradcast 函数) 将消息发送到的所有组内的设备。 通过 messageReceived 事件从其他设备接收消息。<font size="4">tizen.wifidirect.addEventListener('messageReceived', function (error, data) {
if (error) {
alert('Error occurred when trying to receive message');
return;
}
chat.addText(data.message);
});</font>
接收消息时我们做的唯一事件是处理错误并添加接收到的文本到聊天域。如果您想要检查代码的详细信息,您可以在 main.js 文件找到它。我希望这篇文章和示例应用程序帮助您了解库的工作原理,以及如何在您的项目中使用它。
文件附件:
hybridwifidirectservice.zip
hybridwifidirectweb.zip
页:
[1]