通过 Wi-Fi 直连创建点对点连接
通过 Wi-Fi 直连(也称为对等连接或点对点连接),您的应用可以在超出蓝牙功能的范围内快速查找附近的设备并与之互动。
通过 Wi-Fi 对等连接(点对点连接)API,应用无需连接到网络或热点就可以连接到附近的设备。如果您的应用旨在成为安全、近距离网络的一部分,则 Wi-Fi 直连选项比传统 Wi-Fi 临时网络更合适,原因如下:
- Wi-Fi 直连支持 WPA2 加密。(一些临时网络仅支持 WEP 加密。)
- 设备可以广播其提供的服务,这有助于其他设备更容易地发现合适的对等设备。
- 在确定哪个设备应该是网络的群组所有者时,Wi-Fi 直连会检查各设备的电源管理、界面和服务功能,并使用该信息选择可最有效处理服务器职责的设备。
- Android 不支持 Wi-Fi 临时模式。
下面介绍如何使用 Wi-Fi 点对点连接查找并连接附近的设备。
设置应用权限<button class="devsite-heading-link button-flat material-icons" type="button" aria-label="复制指向此部分的链接:设置应用权限" data-title="复制指向此部分的链接:设置应用权限" data-id="permissions"></button>
如需使用 Wi-Fi 点对点,请在清单中添加 ACCESS_FINE_LOCATION
、CHANGE_WIFI_STATE
、ACCESS_WIFI_STATE
和 INTERNET
权限。尽管 Wi-Fi P2P 不需要互联网连接,但它使用标准 Java 套接字,而这需要获得 INTERNET
权限。除了上面的权限外,以下 API 还需要启用位置信息模式:
discoverPeers
discoverServices
requestPeers
设置广播接收器和对等连接管理器<button class="devsite-heading-link button-flat material-icons" type="button" aria-label="复制指向此部分的链接:设置广播接收器和对等连接管理器" data-title="复制指向此部分的链接:设置广播接收器和对等连接管理器" data-id="receiver"></button>
如需使用 Wi-Fi 点对点连接,您需要监听广播 intent,其告知您的应用某些事件是何时发生的。在您的应用中,实例化 IntentFilter
并将其设置为监听以下内容:
WIFI_P2P_STATE_CHANGED_ACTION
- 指示是否启用 Wi-Fi 点对点连接
WIFI_P2P_PEERS_CHANGED_ACTION
- 指示可用的对等设备列表已更改。
WIFI_P2P_CONNECTION_CHANGED_ACTION
- 指示 Wi-Fi 点对点连接的状态已更改。从 Android 10 开始,这不是固定的。如果您的应用依赖于在注册时接收这些广播(因为其之前一直是固定的),请在初始化时使用适当的
get
方法获取信息。 WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
- 指示此设备的配置详细信息已更改。从 Android 10 开始,这不是固定的。如果您的应用依赖于在注册时接收这些广播(因为其之前一直是固定的),请在初始化时使用适当的
get
方法获取信息。
启动对等设备发现<button class="devsite-heading-link button-flat material-icons" type="button" aria-label="复制指向此部分的链接:启动对等设备发现" data-title="复制指向此部分的链接:启动对等设备发现" data-id="discover"></button>
如需使用 Wi-Fi 点对点连接开始搜索附近的设备,请调用 discoverPeers()
。此方法采用以下参数:
WifiP2pManager.Channel
,在初始化对等设备 mManager 时收回的参数WifiP2pManager.ActionListener
的实现,包含系统为成功和未成功发现调用的方法。
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
// Code for when the discovery initiation is successful goes here.
// No services have actually been discovered yet, so this method
// can often be left blank. Code for peer discovery goes in the
// onReceive method, detailed below.
}
@Override
public void onFailure(int reasonCode) {
// Code for when the discovery initiation fails goes here.
// Alert the user that something went wrong.
}
});
获取对等设备列表<button class="devsite-heading-link button-flat material-icons" type="button" aria-label="复制指向此部分的链接:获取对等设备列表" data-title="复制指向此部分的链接:获取对等设备列表" data-id="fetch"></button>
现在编写获取并处理对等设备列表的代码。首先实现 WifiP2pManager.PeerListListener
接口,该接口提供有关 Wi-Fi 点对点连接检测到的对等设备的信息。通过这些信息,您的应用还可以确定对等设备何时加入或离开网络。以下代码段展示了这些与对等设备相关的操作:
private List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
...
private PeerListListener peerListListener = new PeerListListener() {
@Override
public void onPeersAvailable(WifiP2pDeviceList peerList) {
List<WifiP2pDevice> refreshedPeers = peerList.getDeviceList();
if (!refreshedPeers.equals(peers)) {
peers.clear();
peers.addAll(refreshedPeers);
// If an AdapterView is backed by this data, notify it
// of the change. For instance, if you have a ListView of
// available peers, trigger an update.
((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();
// Perform any other updates needed based on the new list of
// peers connected to the Wi-Fi P2P network.
}
if (peers.size() == 0) {
Log.d(WiFiDirectActivity.TAG, "No devices found");
return;
}
}
}
连接到对等设备<button class="devsite-heading-link button-flat material-icons" type="button" aria-label="复制指向此部分的链接:连接到对等设备" data-title="复制指向此部分的链接:连接到对等设备" data-id="connect"></button>
如需连接到对等设备,请创建一个新的 WifiP2pConfig
对象,并从代表您要连接到的设备的 WifiP2pDevice
将数据复制到该对象中。然后调用 connect()
方法。
@Override
public void connect() {
// Picking the first device found on the network.
WifiP2pDevice device = peers.get(0);
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
config.wps.setup = WpsInfo.PBC;
manager.connect(channel, config, new ActionListener() {
@Override
public void onSuccess() {
// WiFiDirectBroadcastReceiver notifies us. Ignore for now.
}
@Override
public void onFailure(int reason) {
Toast.makeText(WiFiDirectActivity.this, "Connect failed. Retry.",
Toast.LENGTH_SHORT).show();
}
});
}
创建群组<button class="devsite-heading-link button-flat material-icons" type="button" aria-label="复制指向此部分的链接:创建群组" data-title="复制指向此部分的链接:创建群组" data-id="create-group"></button>
如果您希望运行应用的设备充当包括传统设备(即不支持 Wi-Fi 直连的设备)的网络的群组所有者,则请遵循连接到对等设备部分中的相同步骤序列,除非您使用 createGroup()
而不是 connect()
创建新的 WifiP2pManager.ActionListener
。WifiP2pManager.ActionListener
中的回调处理方式相同,如以下代码段所示:
manager.createGroup(channel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
// Device is ready to accept incoming connections from peers.
}
@Override
public void onFailure(int reason) {
Toast.makeText(WiFiDirectActivity.this, "P2P group creation failed. Retry.",
Toast.LENGTH_SHORT).show();
}
});
注意:如果网络中的所有设备都支持 Wi-Fi 直连,则可在每个设备上使用 connect()
方法,因为该方法随后将自动创建群组并选择群组所有者。
创建群组后,可以调用 requestGroupInfo()
检索有关网络上对等设备的详细信息,包括设备名称和连接状态。
<button class="devsite-heading-link button-flat material-icons" type="button" aria-label="复制指向此部分的链接:设置应用权限" data-title="复制指向此部分的链接:设置应用权限" data-id="permissions"></button>