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);
    }
}
相关推荐
程序员老刘15 分钟前
Google突然“变脸“,2026年要给全球开发者上“紧箍咒“?
android·flutter·客户端
Tans518 分钟前
Androidx Lifecycle 源码阅读笔记
android·android jetpack·源码阅读
雨白1 小时前
实现双向滑动的 ScalableImageView(下)
android
峥嵘life1 小时前
Android Studio新版本编译release版本apk实现
android·ide·android studio
studyForMokey3 小时前
【Android 消息机制】Handler
android
敲代码的鱼哇3 小时前
跳转原生系统设置插件 支持安卓/iOS/鸿蒙UTS组件
android·ios·harmonyos
翻滚丷大头鱼3 小时前
android View详解—动画
android
我是好小孩3 小时前
[Android]RecycleView的item用法
android
胖虎14 小时前
Android Studio 读取本地文件(以 ZIP 为例)
android·ide·android studio·本地文件·读取本地文件
出海小纸条4 小时前
Google Play 跨应用脚本漏洞(Cross-App Scripting)
android