通过WiFi发送请求(无连接),即使Android M上的移动数据已打开(有连接)
我必须在没有互联网连接的情况下将UDP数据包发送到WiFi模块(配有自己的AP),但当我将手机连接到AP时,Android会在手机数据接口上重定向我的数据包,因为它已连接互联网 我使用了下面的代码来完成我的工作,但在安卓M上似乎不起作用通过WiFi发送请求(无连接),即使Android M上的移动数据已打开(有连接),android,networking,android-wifi,android-6.0-marshmallow,iot,Android,Networking,Android Wifi,Android 6.0 Marshmallow,Iot,我必须在没有互联网连接的情况下将UDP数据包发送到WiFi模块(配有自己的AP),但当我将手机连接到AP时,Android会在手机数据接口上重定向我的数据包,因为它已连接互联网 我使用了下面的代码来完成我的工作,但在安卓M上似乎不起作用 @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void setWifiInterfaceAsDefault() { ConnectivityManager connectivityManager = (
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setWifiInterfaceAsDefault() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder = new NetworkRequest.Builder();
NetworkRequest networkRequest= builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
connectivityManager.requestNetwork(networkRequest, new ConnectivityManager.NetworkCallback());
}
我还加了一句
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
在我的AndroidManifest.xml上,我确保Settings.System.canWrite(this)
返回true
,但仍然没有返回任何内容
提前感谢。使用ConnectionManager绑定网络。setProcessDefaultNetwork()防止漫游并允许完全TCP访问。因此,在onAvailable()回调中,您可以将应用程序进程绑定到该网络,而不是打开到特定URL的连接
ConnectivityManager connection_manager =
(ConnectivityManager) activity.getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connection_manager.registerNetworkCallback(request.build(), new NetworkCallback() {
@Override
public void onAvailable(Network network) {
ConnectivityManager.setProcessDefaultNetwork(network);
}
}
的答案是正确的,但不完整,因为只在棒棒糖中有效
我已经为棒棒糖和棉花糖编写了一个完整的解决方案,供您在连接到您选择的特定网络时通过WiFi路由所有网络请求
科特林 在您的活动中
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class RoutingActivity : Activity() {
private var mConnectivityManager: ConnectivityManager? = null
private var mNetworkCallback: ConnectivityManager.NetworkCallback? = null
//...
override fun onCreate(savedInstanceState: Bundle?) {
//...
routeNetworkRequestsThroughWifi("Access-Point-SSID-You-Want-To-Route-Your-Requests")
}
通过WiFi路由来自应用程序的未来网络请求(即使给定的WiFi网络没有互联网,且移动数据具有互联网连接)
取消注册网络回调
创建网络路由
释放网络路由
帮手
我的朋友你找到解决办法了吗?我有确切的要求。我已经在物联网设备上做了一个模拟连接的变通方法,让安卓认为物联网设备有连接。您可以在服务器根目录上放置一个名为generate_204的空文件,并向服务器dns添加一些URL。我知道这是一个奇怪的解决办法,但对我来说是有效的。希望我帮了你。谢谢,但不幸的是,这不是我的选择。物联网设备不在我的控制范围内。如果您能找到真正的解决方案,请告诉我们✌@AlimuZi我也有类似的问题,你介意提供更多关于你的GuangTy204工作的信息吗?因为我可以对设备进行修改。这里可以找到更多的信息:你应该考虑写下自己的博客文章。这仍然是一个记录不足的话题,有着源源不断的问题,你在这里和在上的文章提供了一个比谷歌博客postMuch更完整、更有用的图片,感谢你的积极反馈@mikeh!请随意写一篇关于这篇内容的文章,我很乐意在你发表之前对其进行评论。谢谢@ryan amaral,这真是太好了。让我看看我能做什么!作品:),谢谢你救了我一天谢谢@Stanislav,很棒的解决方案。它也为mashmallow和Naugat工作。你真的救了我一天。谢谢。这在Android P中也适用。如果需要,我稍后还会尝试实现Ryan的代码。
/**
* This method sets a network callback that is listening for network changes and once is
* connected to the desired WiFi network with the given SSID it will bind to that network.
*
* Note: requires android.permission.INTERNET and android.permission.CHANGE_NETWORK_STATE in
* the manifest.
*
* @param ssid The name of the WiFi network you want to route your requests
*/
private fun routeNetworkRequestsThroughWifi(ssid: String) {
mConnectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
// ensure prior network callback is invalidated
unregisterNetworkCallback(mNetworkCallback)
// new NetworkRequest with WiFi transport type
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build()
// network callback to listen for network changes
mNetworkCallback = object : ConnectivityManager.NetworkCallback() {
// on new network ready to use
override fun onAvailable(network: Network) {
if (getNetworkSsid(this@RoutingActivity).equals(ssid, ignoreCase = false)) {
releaseNetworkRoute()
createNetworkRoute(network)
} else {
releaseNetworkRoute()
}
}
}
mConnectivityManager?.requestNetwork(request, mNetworkCallback)
}
private fun unregisterNetworkCallback(networkCallback: ConnectivityManager.NetworkCallback?) {
if (networkCallback != null) {
try {
mConnectivityManager?.unregisterNetworkCallback(networkCallback)
} catch (ignore: Exception) {
} finally {
mNetworkCallback = null
}
}
}
private fun createNetworkRoute(network: Network): Boolean? {
var processBoundToNetwork: Boolean? = false
when {
// 23 = Marshmallow
Build.VERSION.SDK_INT >= 23 -> {
processBoundToNetwork = mConnectivityManager?.bindProcessToNetwork(network)
}
// 21..22 = Lollipop
Build.VERSION.SDK_INT in 21..22 -> {
processBoundToNetwork = ConnectivityManager.setProcessDefaultNetwork(network)
}
}
return processBoundToNetwork
}
private fun releaseNetworkRoute(): Boolean? {
var processBoundToNetwork: Boolean? = false
when {
// 23 = Marshmallow
Build.VERSION.SDK_INT >= 23 -> {
processBoundToNetwork = mConnectivityManager?.bindProcessToNetwork(null)
}
// 21..22 = Lollipop
Build.VERSION.SDK_INT in 21..22 -> {
processBoundToNetwork = ConnectivityManager.setProcessDefaultNetwork(null)
}
}
return processBoundToNetwork
}
private fun getNetworkSsid(context: Context?): String {
// WiFiManager must use application context (not activity context) otherwise a memory leak can occur
val mWifiManager = context?.applicationContext?.getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiInfo: WifiInfo? = mWifiManager.connectionInfo
if (wifiInfo?.supplicantState == SupplicantState.COMPLETED) {
return wifiInfo.ssid.removeSurrounding("\"")
}
return ""
}