Android 应用wifi direct连接通信实现

一. 打开Wi-Fi direct

1.必须启用Wi-Fi功能:在设备设置中开启Wi-Fi主开关(即使未连接路由器)

关闭冲突功能:若已开启「热点共享」或连接到其他Wi-Fi网络,需先关闭相关功能以避免硬件占.

<!-- Wi-Fi Direct 核心权限 -->

<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"/>

<!-- Android 10+ 需位置权限 -->

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

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

1.1.代码调用打开WIFI

// 获取Wi-Fi管理器实例

WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);

// 开启Wi-Fi

if (!wifiManager.isWifiEnabled()) {

wifiManager.setWifiEnabled(true); // API 28以下可调用,高版本需跳转系统设置页‌:ml-citation{ref="1,4" data="citationList"}

}

1.2.跳转系统Wi-Fi设置页(适用于无法直接控制Wi-Fi的情况)

startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));

2.在系统设置中进入Wi-Fi菜单,点击右上角「高级」选项,找到并启用Wi-Fi Direct(部分设备显示为「WLAN直连」或「附近设备」)

  1. 位置权限开关

Android 10及以上版本:需在设置中打开位置信息(GPS)权限,否则Wi-Fi Direct功能可能被禁用或无法扫描设备

动态权限申请:应用需通过弹窗申请ACCESS_FINE_LOCATION权限,用户需手动授

二.连接设备,数据通信

1.客户端设备处理

1.1 客户端注册广播监听

注册广播监听,包括:

#1.启用/禁用 Wi-Fi P2P 功能。

#2.扫描到附近的设备或者当设备处于可发现状态

#3.连接状态变化

java 复制代码
WifiP2pManager manager = (WifiP2pManager) MyApplication.getAppContext().getSystemService(Context.WIFI_P2P_SERVICE);
WifiP2pManager.Channel channel = manager.initialize(MyApplication.getAppContext(), getMainLooper(), null);
// 客户端设备(主动发起连接的设备)注册广播接收器监听设备发现
private BroadcastReceiver clientReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
            // 检查 Wi-Fi Direct 是否启用
            int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
            if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
                // 功能已启用,一般是收到功能已启用执行1.设备发现
                discoverPeers();
            } else {
                // 功能未启用
            }
        } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
            // 监听扫描到附近的设备或者当设备处于可发现状态(如其他设备开启 P2P 搜索或加入/退出网络)
            manager.requestPeers(channel, peerList -> {
                // 处理设备列表
                Collection<WifiP2pDevice> devices = peerList.getDeviceList();
                // 更新 UI 显示设备列表
                for (WifiP2pDevice device : devices) {
                    //选择需要连接的WifiP2pDevice设备,
                    clientConnectP2pDevice(MacAddress.fromString(device.deviceAddress));
                }
            });
        } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
            //连接状态变化监听 如服务端接受连接并创建组后
            manager.requestConnectionInfo(channel, info -> {
                InetAddress groupOwnerAddress = info.groupOwnerAddress;
                if (info.groupFormed && !info.isGroupOwner) {
                    // 客户端逻辑:连接群主 IP 的指定端口
                    try {
                        clientSocketConnect(context, groupOwnerAddress.getHostAddress());
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                } else if (info.isGroupOwner) {
                    // 群主逻辑:启动服务端 Socket 这里是客户端不会处理这段
                }
            });
        }
    }
};

/**
 * 客户端步骤1
 * 注册广播监听,包括:
 *  1.启用/禁用 Wi-Fi P2P 功能。
 *  2.扫描到附近的设备或者当设备处于可发现状态
 *  3.连接状态变化
 */
private void clientRegisterWifiListen() {
    // 注册接收器
    IntentFilter intentFilter = new IntentFilter();
    //WIFI_P2P_STATE_CHANGED_ACTION监听 启用/禁用 Wi-Fi P2P 功能
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
    MyApplication.getAppContext().registerReceiver(clientReceiver, intentFilter);
}

1.2 主动搜索设备

客户端在检查 Wi-Fi Direct已启用时,主动搜索设备

java 复制代码
/**
 * 客户端步骤2
 * 客户端在检查 Wi-Fi Direct已启用时,主动搜索设备
 */
private void discoverPeers() {
    manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
        @Override
        public void onSuccess() {
            // 发现设备成功,客户端会收到WIFI_P2P_PEERS_CHANGED_ACTION广播
        }

        @Override
        public void onFailure(int reason) {
            // 失败处理
        }
    });
}

1.3 选择设备连接

客户端在扫描到附近设备,选择设备连接

java 复制代码
/**
 * 客户端步骤3
 * 客户端在扫描到附近设备,选择设备连接
 *
 * @param targetDeviceAddress
 */
private void clientConnectP2pDevice(MacAddress targetDeviceAddress) {
    WifiP2pConfig config = new WifiP2pConfig.Builder()
            .setDeviceAddress(targetDeviceAddress)
            .build();
    manager.connect(channel, config, new WifiP2pManager.ActionListener() {
        @Override
        public void onSuccess() {
            //连接成功后
        }

        @Override
        public void onFailure(int reason) {

        }
    });
      //发起 connect() 请求后,需验证连接是否成功建立
    manager.requestConnectionInfo(channel, info -> {
        InetAddress groupOwnerAddress = info.groupOwnerAddress;
        if (info.groupFormed && !info.isGroupOwner) {
            // 客户端逻辑:连接群主 IP 的指定端口
            try {
                clientSocketConnect(MyApplication.getAppContext(), groupOwnerAddress.getHostAddress());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else if (info.isGroupOwner) {
            // 群主逻辑:启动服务端 Socket 这里是客户端不会处理这段
        }
    });
}

1.4 socket连接数据通信

客户端在监听到连接状态变化(服务端同意连接并创建组)获取到服务端ip地址和服务端创建的socket端口进行数据通信。

java 复制代码
/**
 * 客户端步骤4
 * 客户端在监听到连接状态变化(服务端同意连接并创建组)获取到服务端ip地址和服务端
 * 创建的socket端口进行数据通信
 *
 * @param context
 * @param serverIP
 * @throws IOException
 */
private void clientSocketConnect(Context context, String serverIP) throws IOException {
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    Socket socket = new Socket();
    socket.connect(new InetSocketAddress(serverIP, 8888));

    //连接之后就可以获取输入输出流进行 读写操作了
    InputStream inputStream = socket.getInputStream();
    OutputStream outputStream = socket.getOutputStream();
}

2.服务端设备处理

2.1 服务端注册广播监听

注册广播监听 连接状态变化(监听到客户端连接请求)

java 复制代码
// 服务端(等待连接的设备)注册广播接收器
private final BroadcastReceiver p2pConnectReceiver = new 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);
            WifiP2pInfo p2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);

            if (networkInfo.isConnected()) {
                // 连接已建立,处理群组信息(如群组所有者 IP 和角色)可进行数据传输

            } else {
                //服务端在收到连接请求后会默认成为组所有者并自动创建组。一般不需要调用acceptConnection
                //若需要确保服务端始终为组所有者(而非由系统自动协商决定),需手动调用 createGroup()
                acceptConnection();
            }
        }
    }
};

/**
 * 服务端步骤1
 * 注册广播监听 连接状态变化(监听到客户端连接请求)
 */
private void serverRegisterWifiListen() {
    // 服务端注册接收器
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
    MyApplication.getAppContext().registerReceiver(p2pConnectReceiver, intentFilter);
}

2.2 接受连接创建群组

服务端如果接受连接后调用 WifiP2pManager.createGroup() 创建群组(作为群组所有者)

若设备需自动接受连接(如预配置场景),可直接调用 createGroup() 或响应连接请求

java 复制代码
/**
 * 服务端步骤2
 * 服务端如果接受连接后调用 WifiP2pManager.createGroup() 创建群组(作为群组所有者)
 * 若设备需自动接受连接(如预配置场景),可直接调用 createGroup() 或响应连接请求
 */
private void acceptConnection() {
    WifiP2pManager manager = (WifiP2pManager) MyApplication.getAppContext().getSystemService(Context.WIFI_P2P_SERVICE);
    WifiP2pManager.Channel channel = manager.initialize(MyApplication.getAppContext(), getMainLooper(), null);
    manager.createGroup(channel, new WifiP2pManager.ActionListener() {
        @Override
        public void onSuccess() {
            //群组创建成功,被连接方成为群组所有者
            //此时客户端会收到WIFI_P2P_PEERS_CHANGED_ACTION广播,且可以获取到当前服务端的WifiP2pDevice对象
            //服务端创建socket 等待连接
            createServiceSocket();
        }

        @Override
        public void onFailure(int reason) {
            // 处理失败逻辑(如显示错误提示)
        }
    });
}

2.3 创建服务端socket 和客户端通信

创建服务端socket等待客户端连接

java 复制代码
/**
 * 服务端步骤3
 * 创建服务端socket等待客户端连接
 */
private void createServiceSocket() {
    ServerSocket serverSocket = null;
    try {
        serverSocket = new ServerSocket(8888);
        Socket clientSocket = serverSocket.accept();
        //连接之后就可以获取输入输出流进行 读写操作了
        InputStream inputStream = clientSocket.getInputStream();
        OutputStream outputStream = clientSocket.getOutputStream();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
相关推荐
李新_1 小时前
Android 多进程并发控制如何实现
android·java
氦客2 小时前
kotlin知识体系(五) :Android 协程全解析,从作用域到异常处理的全面指南
android·开发语言·kotlin·协程·coroutine·suspend·functions
Mr YiRan3 小时前
Android Gradle多渠道打包
android
IvanCodes4 小时前
MySQL 视图
android·数据库·sql·mysql·oracle
KevinWang_4 小时前
Java 和 Kotlin 混编导致的 bug
android·kotlin
好学人4 小时前
Android动画系统全面解析
android
leverge20094 小时前
android studio 运行java main报错
android·ide·android studio
RichardLai884 小时前
Flutter 环境搭建
android·flutter
思想觉悟4 小时前
ubuntu编译android12源码
android·ubuntu·源码