如何为Wi-Fi P2P网络调用bindProcessToNetwork绑定进程?
问题
我在Android平台使用Wi-Fi P2P网络连接IoT设备,连接已成功建立,该设备运行DHCP服务器,相关代码如下:
private class WiFiDirectBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO); PRINTF("WiFiDirect WIFI_P2P_CONNECTION_CHANGED_ACTION " + networkInfo.getState()); if (networkInfo.getState() == NetworkInfo.State.CONNECTED) { mManager.requestConnectionInfo(mChannel, new WifiP2pManager.ConnectionInfoListener() { @Override public void onConnectionInfoAvailable(WifiP2pInfo info) { //This function is reached. The device can be pinged to //info.groupOwnerAddress.getHostAddress() } }); } }
我希望将进程绑定到该P2P网络,已添加网络注册回调,该回调在普通热点场景下会触发,但在Wi-Fi P2P场景下从未被调用:
NetworkRequest nr = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .addCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P).build(); mConnectivityManager.registerNetworkCallback(nr, new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { super.onAvailable(network); //This is never being called for P2P mConnectivityManager.bindProcessToNetwork(network); } });
请问我是否遗漏了什么配置?或者,如何在WiFiDirectBroadcastReceiver中从NetworkInfo获取对应的Network对象?
解决方案
一、NetworkCallback未触发的修复方案
- 补全必要权限
确保Manifest中声明以下权限,Wi-Fi P2P相关操作依赖这些权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
其中ACCESS_FINE_LOCATION是Android 10及以上版本要求的,CHANGE_NETWORK_STATE用于进程绑定网络操作。
- 调整NetworkRequest配置
部分设备的Wi-Fi P2P网络未正确标记NET_CAPABILITY_WIFI_P2P,可以尝试简化NetworkRequest的筛选条件:
NetworkRequest nr = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) // 部分设备需要这个标记 .build();
如果还是不触发,可在连接成功后主动遍历所有网络查找目标P2P网络:
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); Network[] networks = cm.getAllNetworks(); for (Network network : networks) { NetworkCapabilities capabilities = cm.getNetworkCapabilities(network); if (capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { // 匹配到Wi-Fi网络,进一步确认是否为P2P NetworkInfo ni = cm.getNetworkInfo(network); if (ni != null && ni.getType() == ConnectivityManager.TYPE_WIFI_P2P && ni.isConnected()) { cm.bindProcessToNetwork(network); break; } } }
二、从NetworkInfo获取Network对象的方法
广播中的NetworkInfo无法直接拿到Network对象,但可以通过以下方式间接匹配:
- 在连接成功后遍历网络匹配
在WIFI_P2P_CONNECTION_CHANGED_ACTION的连接分支中,通过ConnectivityManager查询所有网络,匹配Wi-Fi P2P类型:
if (networkInfo.getState() == NetworkInfo.State.CONNECTED) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); Network[] networks = cm.getAllNetworks(); for (Network network : networks) { NetworkInfo ni = cm.getNetworkInfo(network); if (ni != null && ni.getType() == ConnectivityManager.TYPE_WIFI_P2P && ni.isConnected()) { cm.bindProcessToNetwork(network); break; } } // 保留原有的requestConnectionInfo逻辑 mManager.requestConnectionInfo(mChannel, ...); }
- 结合WifiP2pInfo的IP地址精准匹配
如果存在多个Wi-Fi网络,可通过WifiP2pInfo中的组所有者IP地址,匹配网络的链路属性:
mManager.requestConnectionInfo(mChannel, new WifiP2pManager.ConnectionInfoListener() { @Override public void onConnectionInfoAvailable(WifiP2pInfo info) { String targetIp = info.groupOwnerAddress.getHostAddress(); ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); Network[] networks = cm.getAllNetworks(); for (Network network : networks) { LinkProperties lp = cm.getLinkProperties(network); if (lp != null) { for (LinkAddress la : lp.getLinkAddresses()) { if (la.getAddress().getHostAddress().equals(targetIp)) { cm.bindProcessToNetwork(network); break; } } } } } });
三、额外提示
如果不需要绑定整个进程,仅需特定Socket使用P2P网络,可使用network.bindSocket(socket)方法,更灵活且避免影响其他网络请求。
内容的提问来源于stack exchange,提问作者gregoiregentil
相关产品推荐
相关产品推荐

