Android(Xamarin)中连接wifi接入点的问题
我目前正在进行一个项目,其中我有一个Android应用程序,需要连接到物联网设备并向其发送一些信息。物联网设备使用带有ATWINC1500 wifi模块的SAMD21微控制器。ATWINC1500能够创建一个wifi接入点,我应该能够从Android设备连接到该接入点。它不支持wifi直接(p2p)连接,也没有任何蓝牙功能。目前,在物联网设备上,我让它创建一个接入点,然后启动一个服务器来监听传入的连接。只是为了获取信息,wifi接入点目前处于开放状态,没有密码或钥匙 我的简化程序流程如下:Android(Xamarin)中连接wifi接入点的问题,android,xamarin,wifi,android-wifi,wifimanager,Android,Xamarin,Wifi,Android Wifi,Wifimanager,我目前正在进行一个项目,其中我有一个Android应用程序,需要连接到物联网设备并向其发送一些信息。物联网设备使用带有ATWINC1500 wifi模块的SAMD21微控制器。ATWINC1500能够创建一个wifi接入点,我应该能够从Android设备连接到该接入点。它不支持wifi直接(p2p)连接,也没有任何蓝牙功能。目前,在物联网设备上,我让它创建一个接入点,然后启动一个服务器来监听传入的连接。只是为了获取信息,wifi接入点目前处于开放状态,没有密码或钥匙 我的简化程序流程如下: 在A
public void ConnectToWifiNetwork(string ssid)
{
if (Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.Q)
{
var wifi_network_specifier = (new WifiNetworkSpecifier.Builder()).SetSsid(ssid).Build();
var network_request = (new NetworkRequest.Builder()).AddTransportType(TransportType.Wifi)
.SetNetworkSpecifier(wifi_network_specifier).Build();
connectivity_manager.RequestNetwork(network_request, network_callback);
}
else if (Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
//See if the desired network configuration already exists
var configured_networks = wifi_manager.ConfiguredNetworks;
var specified_network = configured_networks.Where(x => x.Ssid.Contains(ssid)).FirstOrDefault();
int network_id = -1;
//If no network configuration already exists....
if (specified_network == null)
{
//Create a wifi configuration with the appropriate SSID
specified_network = new WifiConfiguration();
specified_network.Ssid = '"' + ssid + '"';
specified_network.AllowedKeyManagement.Set((int)Android.Net.Wifi.KeyManagementType.None);
//Add the configuration to the wifi manager's list of configured networks
network_id = wifi_manager.AddNetwork(specified_network);
}
else
{
//Otherwise, if a network configuration does already exist, grab the network ID
network_id = specified_network.NetworkId;
}
//If we have a valid network ID...
if (network_id != -1)
{
//Let's attempt to connect to the network
wifi_manager.Disconnect();
wifi_manager.EnableNetwork(network_id, true);
wifi_manager.Reconnect();
//Now let's bind to the network we just connected to
var network_request = (new NetworkRequest.Builder()).AddTransportType(TransportType.Wifi).Build();
connectivity_manager.RequestNetwork(network_request, network_callback);
}
}
}
请注意,变量connectivity\u manager
和wifi\u manager
在代码的其他地方定义,它们分别属于ConnectivityManager
和WifiManager
类型。另外,network\u callback
变量也在代码中的其他地方定义,它的类型为WifiConnectorNetworkCallback
,我将其定义为:
class WifiConnectorNetworkCallback : ConnectivityManager.NetworkCallback
{
WifiConnector source;
public WifiConnectorNetworkCallback(WifiConnector p)
{
source = p;
}
public override void OnAvailable(Network network)
{
source.connectivity_manager.BindProcessToNetwork(network);
source.WifiNetworkConnected?.Invoke(source, new EventArgs());
}
public override void OnUnavailable()
{
base.OnUnavailable();
}
}
private void WifiNetworkConnected(object sender, EventArgs e)
{
TcpClient client = new TcpClient();
client.Connect(IPAddress.Parse("192.168.1.1"), 80);
//Create a network stream to send data
NetworkStream writer = client.GetStream();
//Write some data
string data = "test";
writer.Write(Encoding.ASCII.GetBytes(data), 0, data.Length);
//Disconnect from the server
writer.Close();
client.Close();
}
最后,您会注意到,当调用“OnAvailable”方法时,它会调用一个事件处理程序。事件处理程序调用的方法是我实际创建TcpClient并尝试连接到IoT设备上的服务器的方法。其定义如下:
class WifiConnectorNetworkCallback : ConnectivityManager.NetworkCallback
{
WifiConnector source;
public WifiConnectorNetworkCallback(WifiConnector p)
{
source = p;
}
public override void OnAvailable(Network network)
{
source.connectivity_manager.BindProcessToNetwork(network);
source.WifiNetworkConnected?.Invoke(source, new EventArgs());
}
public override void OnUnavailable()
{
base.OnUnavailable();
}
}
private void WifiNetworkConnected(object sender, EventArgs e)
{
TcpClient client = new TcpClient();
client.Connect(IPAddress.Parse("192.168.1.1"), 80);
//Create a network stream to send data
NetworkStream writer = client.GetStream();
//Write some data
string data = "test";
writer.Write(Encoding.ASCII.GetBytes(data), 0, data.Length);
//Disconnect from the server
writer.Close();
client.Close();
}
现在,我发现程序可以以几种不同的方式运行。如果我在Android 8.1设备上运行该应用程序,则在许多其他问题/答案中发现的典型3行代码无法连接到wifi AP:
wifi_manager.Disconnect();
wifi_manager.EnableNetwork(network_id, true);
wifi_manager.Reconnect();
我必须包括从ConnectivityManager
类调用RequestNetwork
,这样它才能连接到wifi AP,这就是为什么存在这行代码的原因:
connectivity_manager.RequestNetwork(network_request, network_callback);
但即使在安卓8.1和安卓10上使用对RequestNetwork
的调用,它仍然不能完全工作。如果我只是停在那里,尝试创建一个TcpClient并连接到AP上的服务器,我会得到一个网络不可访问的异常
因此,经过大量的研究和挖掘,我决定在调用RequestNetwork
后,在OnAvailable
方法中添加以下代码行:
parent.connectivity_manager.BindProcessToNetwork(network);
这有时似乎有帮助。它使我使用TcpClient连接AP的成功率从0%提高到10%或20%,但不幸的是,现在我经常遇到连接被拒绝的异常
现在,我似乎有一种方法获得了100%的成功率:如果我使用Android设置应用程序手动连接到wifi AP,然后返回Android应用程序并创建TcpClient,它似乎每次都能成功运行。因此,我不认为物联网微控制器方面存在缺陷。Android中似乎发生了一些事情,如果我手动连接到AP,它可以正常工作,但是使用上面描述的代码连接到AP,我总是会遇到“网络不可访问”或“连接被拒绝”异常
有人能帮我澄清为什么我会遇到这些例外情况吗?在连接AP时,我是否缺少一个步骤?谢谢你的帮助 Android Q上的这个新API非常感谢您链接到您优秀的博客文章。事实上,看起来我们的方法非常相似。如果我以前手动添加网络,我似乎会获得更好的成功,但这违背了我正在尝试的目的。我希望物联网设备上的wifi模块支持P2P连接,这样我就可以使用该API,但可惜它没有。我正在考虑切换到另一个支持BLE的模块,希望Android BLE API和该模块可以更好地相互配合。