如何在 C# Xamarin Android 应用程序中先连接到本地网络而不是互联网?
How to connect to local network first instead of internet in C# Xamarin Android app?
我有一个 Xamarin Android 应用程序。它连接到某些 IOT 设备的“无基于互联网的 Wifi 路由器”。但它也需要使用手机的蜂窝数据在 Dropbox 上存储一些信息。
现在工作如下:
- 我可以通过编程方式打开 on/off Wifi 连接。
- 我无法打开 on/off 蜂窝数据(因为 Android L)。它不允许在非根设备上使用。
- 当我的 phone 连接到这个本地 Wifi 路由器并且蜂窝数据也打开时,Android 默认工作方式,它使用来自蜂窝连接的互联网和我对 Dropbox 的所有调用工作没有任何问题。
- 但是,当本地 Wifi“没有互联网”时,这种对蜂窝网络的偏好导致我的应用程序永远无法连接到本地设备。假设我的一个设备正在侦听端口 9000 上的 IP 192.168.2.3,当我尝试连接到它时,我的代码通过蜂窝数据搜索它并且找不到 returns 主机。
- 那么在这种情况下有没有办法连接到本地设备?
- 作为解决方法,我手动提供了模式弹出窗口,以指示用户在需要“非”Dropbox 调用(例如连接到 IOT 设备)时禁用 Cellular。但这不是一个好的用户体验,因为用户必须不断地手动更改网络。我希望代码以更透明的方式处理这个问题。
请指教。
我能想到的解决方案是,您可以尝试使用 Xamarin.Essentials 并检查连接配置文件,并使用它强制将请求发送到您的 Wifi,而其他请求则通过蜂窝数据
var profiles = Connectivity.ConnectionProfiles;
if (profiles.Contains(ConnectionProfile.WiFi))
{
// Active Wi-Fi connection.
}
可以找到文档 here。
使用Plugin.Essentials(需要一个NetStandard项目)并参考这个link:
https://docs.microsoft.com/en-us/xamarin/essentials/connectivity?tabs=android
尝试本地访问而不是网络。
经过多次尝试和失败后,我能够实施此处提供的方法:
我将此代码从 Java 更改为 Xamarin C#,并且能够以编程方式强制将蜂窝网络或 Wifi 作为首选网络。
我的实现:
using Android.Net;
public SomeClass{
public static Context _context = Android.App.Application.Context;
....
/// <summary>
/// Forces the wifi over cellular.
/// </summary>
public static void ForceWifiOverCellular()
{
ConnectivityManager connection_manager = (ConnectivityManager)_context.GetSystemService(Context.ConnectivityService);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.AddTransportType(TransportType.Wifi);
var callback = new ConnectivityManager.NetworkCallback();
connection_manager.RegisterNetworkCallback(request.Build(), new CustomNetworkAvailableCallBack());
}
/// <summary>
/// Forces the cellular over wifi.
/// </summary>
public static void ForceCellularOverWifi()
{
ConnectivityManager connection_manager = (ConnectivityManager)_context.GetSystemService(Context.ConnectivityService);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.AddTransportType(TransportType.Cellular);
connection_manager.RegisterNetworkCallback(request.Build(), new CustomNetworkAvailableCallBack());
}
}
/// <summary>
/// Custom network available call back.
/// </summary>
public class CustomNetworkAvailableCallBack : ConnectivityManager.NetworkCallback
{
public static Context _context = Android.App.Application.Context;
ConnectivityManager connection_manager = (ConnectivityManager)_context.GetSystemService(Context.ConnectivityService);
public override void OnAvailable(Network network)
{
//ConnectivityManager.SetProcessDefaultNetwork(network); //deprecated (but works even in Android P)
connection_manager.BindProcessToNetwork(network); //this works in Android P
}
}
用法:
- 我需要强制移动电话的地方,只需拨打:
SomeClass.ForceCellularOverWifi();
- 需要强制Wifi的地方,拨打:
SomeClass.ForceWifiOverCellular();
希望这对其他人有帮助。
我有一个 Xamarin Android 应用程序。它连接到某些 IOT 设备的“无基于互联网的 Wifi 路由器”。但它也需要使用手机的蜂窝数据在 Dropbox 上存储一些信息。
现在工作如下:
- 我可以通过编程方式打开 on/off Wifi 连接。
- 我无法打开 on/off 蜂窝数据(因为 Android L)。它不允许在非根设备上使用。
- 当我的 phone 连接到这个本地 Wifi 路由器并且蜂窝数据也打开时,Android 默认工作方式,它使用来自蜂窝连接的互联网和我对 Dropbox 的所有调用工作没有任何问题。
- 但是,当本地 Wifi“没有互联网”时,这种对蜂窝网络的偏好导致我的应用程序永远无法连接到本地设备。假设我的一个设备正在侦听端口 9000 上的 IP 192.168.2.3,当我尝试连接到它时,我的代码通过蜂窝数据搜索它并且找不到 returns 主机。
- 那么在这种情况下有没有办法连接到本地设备?
- 作为解决方法,我手动提供了模式弹出窗口,以指示用户在需要“非”Dropbox 调用(例如连接到 IOT 设备)时禁用 Cellular。但这不是一个好的用户体验,因为用户必须不断地手动更改网络。我希望代码以更透明的方式处理这个问题。
请指教。
我能想到的解决方案是,您可以尝试使用 Xamarin.Essentials 并检查连接配置文件,并使用它强制将请求发送到您的 Wifi,而其他请求则通过蜂窝数据
var profiles = Connectivity.ConnectionProfiles;
if (profiles.Contains(ConnectionProfile.WiFi))
{
// Active Wi-Fi connection.
}
可以找到文档 here。
使用Plugin.Essentials(需要一个NetStandard项目)并参考这个link:
https://docs.microsoft.com/en-us/xamarin/essentials/connectivity?tabs=android
尝试本地访问而不是网络。
经过多次尝试和失败后,我能够实施此处提供的方法:
我将此代码从 Java 更改为 Xamarin C#,并且能够以编程方式强制将蜂窝网络或 Wifi 作为首选网络。
我的实现:
using Android.Net;
public SomeClass{
public static Context _context = Android.App.Application.Context;
....
/// <summary>
/// Forces the wifi over cellular.
/// </summary>
public static void ForceWifiOverCellular()
{
ConnectivityManager connection_manager = (ConnectivityManager)_context.GetSystemService(Context.ConnectivityService);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.AddTransportType(TransportType.Wifi);
var callback = new ConnectivityManager.NetworkCallback();
connection_manager.RegisterNetworkCallback(request.Build(), new CustomNetworkAvailableCallBack());
}
/// <summary>
/// Forces the cellular over wifi.
/// </summary>
public static void ForceCellularOverWifi()
{
ConnectivityManager connection_manager = (ConnectivityManager)_context.GetSystemService(Context.ConnectivityService);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.AddTransportType(TransportType.Cellular);
connection_manager.RegisterNetworkCallback(request.Build(), new CustomNetworkAvailableCallBack());
}
}
/// <summary>
/// Custom network available call back.
/// </summary>
public class CustomNetworkAvailableCallBack : ConnectivityManager.NetworkCallback
{
public static Context _context = Android.App.Application.Context;
ConnectivityManager connection_manager = (ConnectivityManager)_context.GetSystemService(Context.ConnectivityService);
public override void OnAvailable(Network network)
{
//ConnectivityManager.SetProcessDefaultNetwork(network); //deprecated (but works even in Android P)
connection_manager.BindProcessToNetwork(network); //this works in Android P
}
}
用法:
- 我需要强制移动电话的地方,只需拨打:
SomeClass.ForceCellularOverWifi();
- 需要强制Wifi的地方,拨打:
SomeClass.ForceWifiOverCellular();
希望这对其他人有帮助。