当前位置:首页 > 行业动态 > 正文

安卓实现wifi通信

基础概念与准备工作

在安卓设备中实现WiFi通信,主要涉及两种场景:

  1. WiFi P2P(Wi-Fi Direct):设备点对点直连,无需路由器。
  2. 传统WiFi网络通信:设备连接到同一WiFi热点后通过IP通信。

权限配置

AndroidManifest.xml 中声明必要权限:

安卓实现wifi通信  第1张

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

注意:安卓6.0+需动态申请 ACCESS_FINE_LOCATION 权限(因WiFi扫描依赖定位权限)。


WiFi P2P 实现步骤

初始化WiFi P2P

WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
WifiP2pManager.Channel channel = manager.initialize(this, mainLooper, new WifiP2pManager.ChannelListener() {
    @Override
    public void onChannelDisconnected() {
        // 通道断开时回调
    }
});

注册BroadcastReceiver监听P2P状态

private final IntentFilter intentFilter = new IntentFilter();
public void onCreate() {
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
    registerReceiver(receiver, intentFilter);
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
            // 处理WiFi P2P状态变化
        } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
            // 处理可用设备列表更新
        } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
            // 处理连接状态变化
        }
    }
};

发现设备并请求连接

// 发现设备
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
    @Override
    public void onSuccess() {
        // 发现成功
    }
    @Override
    public void onFailure(int reason) {
        // 失败处理
    }
});
// 连接目标设备
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = targetDevice.deviceAddress;
manager.connect(channel, config, new WifiP2pManager.ActionListener() {
    @Override
    public void onSuccess() {
        // 连接成功
    }
    @Override
    public void onFailure(int reason) {
        // 连接失败
    }
});

数据传输(Socket通信)

当连接建立后,系统会分配本地IP地址,可通过 ServerSocketSocket 进行通信:

// 服务器端(接收方)
ServerSocket serverSocket = new ServerSocket(8888);
Socket socket = serverSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message = reader.readLine(); // 读取数据
// 客户端(发送方)
Socket socket = new Socket(targetIP, 8888);
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writer.println("Hello WiFi P2P"); // 发送数据

传统WiFi网络通信(同一热点下)

获取设备IP地址

WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
String ipAddress = Formatter.formatIpAddress(wifiManager.getConnectionInfo().getIpAddress());

通过Socket通信

// 服务器端(监听端口)
ServerSocket serverSocket = new ServerSocket(5000);
Socket socket = serverSocket.accept();
DataInputStream dis = new DataInputStream(socket.getInputStream());
String data = dis.readUTF(); // 接收数据
// 客户端(连接服务器)
Socket socket = new Socket("服务器IP", 5000);
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF("Hello WiFi"); // 发送数据

关键步骤与API对照表

步骤 API/方法 权限 注意事项
初始化WiFi P2P WifiP2pManager.initialize() ACCESS_FINE_LOCATION 需在主线程调用
发现设备 WifiP2pManager.discoverPeers() 需处理 WIFI_P2P_PEERS_CHANGED
请求连接 WifiP2pManager.connect() 需对方接受连接
获取连接信息 WifiP2pInfo.groupOwnerAddress 区分Group Owner和非Group Owner
传统WiFi通信(Socket) Socket, ServerSocket INTERNET 确保设备在同一局域网

相关问题与解答

问题1:WiFi P2P连接成功后如何判断自己是Group Owner?

解答
onReceive() 中监听 WIFI_P2P_CONNECTION_CHANGED_ACTION,通过 WifiP2pInfoisGroupOwner 方法判断角色:

WifiP2pInfo info = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
if (info.isGroupOwner) {
    // 当前设备是Group Owner,可启动ServerSocket
} else {
    // 当前设备是Client,需连接Group Owner的IP
}

问题2:传统WiFi通信中如何动态获取服务器IP?

解答

  1. 服务器端在启动 ServerSocket 后,通过 getLocalInetAddress()wifiManager.getConnectionInfo().getIpAddress() 获取IP。
  2. 客户端需提前知道服务器IP(可通过UI输入或广播通知)。
  3. 示例代码:
    // 服务器获取IP
    InetAddress serverIp = InetAddress.getByName(wifiManager.getConnectionInfo().getIpAddress());
    // 客户端连接
    new Socket(serverIp, 5000);
0