android wifi直连 wifip2pmanager
android wifi直连 wifip2pmanager;使用WiFi 直连,然后通过udp进行通讯。
Android WiFi 直连(Wi-Fi Direct,也称为Wi-Fi P2P)是一种让两台或多台设备通过Wi-Fi技术直接进行点对点连接的技术,无需借助传统的无线路由器或接入点。这种技术使得设备间可以快速建立安全的无线连接,实现文件传输、屏幕共享、游戏对战等多种应用,尤其适用于智能手机、平板电脑、打印机、相机等消费电子设备间的近距离通信。
以下是Android WiFi 直连的基本工作原理和使用步骤:
工作原理:
设备发现:启用Wi-Fi Direct功能的设备可以通过广播信号搜索和发现附近的其他支持Wi-Fi Direct的设备。设备间可以互相检测到对方的存在,并显示在设备列表中供用户选择。
连接请求:用户在设备列表中选择要连接的目标设备后,发起连接请求。目标设备收到请求后,通常需要手动或自动确认接受连接。
组建立:一旦连接请求被接受,两台设备之间会自动建立一个Wi-Fi Direct组。在这个组中,一台设备会被选为“组主人”(Group Owner,GO),相当于小型网络的接入点,负责管理组内的连接和数据传输。另一台设备则作为“客户端”(Client)加入该组。
数据传输:连接建立后,组主人和客户端设备可以使用各自的IP地址和端口号进行直接的TCP/UDP通信。应用程序可以利用这些网络参数创建Socket连接,进行文件传输、消息传递等操作。
例子代码:
public class WifiConnectActivity extends AppCompatActivity {private Button btnConnect;private WifiDirectLink wifiDirectLink;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);LinearLayout linearLayout = new LinearLayout(this);linearLayout.setOrientation(LinearLayout.VERTICAL);setContentView(linearLayout);btnConnect = new AppCompatButton(this);btnConnect.setText("链接");AppCompatButton btnConnect2 = new AppCompatButton(this);btnConnect2.setText("发送");linearLayout.addView(btnConnect);linearLayout.addView(btnConnect2);wifiDirectLink = new WifiDirectLink(getApplicationContext());// 按钮点击事件 - 连接到对等设备btnConnect.setOnClickListener(v -> wifiDirectLink.connectToPeer());btnConnect2.setOnClickListener(v -> wifiDirectLink.send("hello".getBytes()));if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.NEARBY_WIFI_DEVICES}, 119);} else {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 119);}}@Overrideprotected void onDestroy() {wifiDirectLink.release();super.onDestroy();}}
连接工具类:
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;import androidx.core.content.ContextCompat;import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;public class WifiDirectLink {private static final String TAG = "WifiDirectLink";private final WifiP2pManager wifiP2pManager;private final WifiP2pManager.Channel channel;private Context context;private final Handler handler = new Handler(Looper.getMainLooper());private SyncUDP udp;private String otherClientIp;public WifiDirectLink(Context context) {this.context = context;Log.i(TAG, "WifiDirectLink: begin start-----------------------------------------------");if (udp == null) {udp = new SyncUDP(Config.BROADCAST_PORT + 3);udp.setListener(this::receiveAction);}// 初始化Wi-Fi P2P管理器和通道wifiP2pManager = (WifiP2pManager) context.getSystemService(Context.WIFI_P2P_SERVICE);channel = wifiP2pManager.initialize(context, Looper.getMainLooper(), null);// 创建意图过滤器并添加所需的意图动作IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);// 注册广播接收器ContextCompat.registerReceiver(context, broadcastReceiver, intentFilter, ContextCompat.RECEIVER_EXPORTED);handler.postDelayed(new Runnable() {@Overridepublic void run() {try {discoverPeers();} catch (Exception e) {e.printStackTrace();}handler.postDelayed(this, 8888);}}, 88);}private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {Log.i(TAG, "onReceive: " + intent.getAction());String action = intent.getAction();if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {// 获取连接信息WifiP2pInfo wifiP2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);if (wifiP2pInfo != null) {new Thread(() -> {// 获取groupOwnerAddressInetAddress groupOwnerAddress = wifiP2pInfo.groupOwnerAddress;// 在这里可以使用groupOwnerAddress进行相应的操作if (groupOwnerAddress != null) {String hostAddress = groupOwnerAddress.getHostAddress();String hostName = groupOwnerAddress.getHostName();byte[] address = groupOwnerAddress.getAddress();String canonicalHostName = groupOwnerAddress.getCanonicalHostName();Log.i(TAG, "onReceive: get host address:" + hostAddress + "; " + hostName + "; " + address + "; " + canonicalHostName);// start socket connectotherClientIp = hostAddress;if (!TextUtils.isEmpty(otherClientIp)) {new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(context.getApplicationContext(), "获取鬣主任ip", Toast.LENGTH_LONG).show());}}}).start();}}}};public void send(byte[] buf) {// 广播 都接受得到Log.i(TAG, "send: other client ip:" + otherClientIp);if (udp == null || otherClientIp == null) return;new Thread(() -> {String substring = otherClientIp.substring(0, otherClientIp.lastIndexOf("."));substring = substring + ".255";udp.sendAction(buf, substring);}).start();}@SuppressLint("MissingPermission")public void discoverPeers() throws Exception {wifiP2pManager.discoverPeers(channel, new WifiP2pManager.ActionListener() {@Overridepublic void onSuccess() {Log.i(TAG, "onSuccess: scan wifi node");}@Overridepublic void onFailure(int i) {Log.i(TAG, "onFailure: No nodes scanned");}});}@SuppressLint("MissingPermission")public void connectToPeer() {Log.i(TAG, "connectToPeer: start connect");wifiP2pManager.requestPeers(channel, wifiP2pDeviceList -> {List<WifiP2pDevice> deviceList = new ArrayList<>(wifiP2pDeviceList.getDeviceList());Log.i(TAG, "connectToPeer: item count:" + deviceList.size());if (deviceList.size() == 0) {return;}for (WifiP2pDevice item : deviceList) {Log.i(TAG, "connectToPeer: item name:" + item.deviceName + "; " + item.deviceAddress);// 创建连接配置WifiP2pConfig config = new WifiP2pConfig();config.deviceAddress = item.deviceAddress;connectItem(config, item);}});}@SuppressLint("MissingPermission")private void connectItem(WifiP2pConfig config, WifiP2pDevice item) {try {wifiP2pManager.connect(channel, config, new WifiP2pManager.ActionListener() {@Overridepublic void onSuccess() {Log.i(TAG, "onSuccess: Link successful for:" + item.deviceName + "; " + item.deviceAddress);}@Overridepublic void onFailure(int reasonCode) {Log.i(TAG, "onFailure: Link failure for:" + item.deviceName + "; " + item.deviceAddress);}});} catch (Exception e) {e.printStackTrace();Log.i(TAG, "getDevices: connect item error:" + e.getMessage());}}private void receiveAction(byte[] buffer, int len, String ip) {Log.i(TAG, "receiveAction: ip:" + ip + "; len:" + len);}public void release() {handler.removeCallbacksAndMessages(null);if (udp != null) {udp.release();udp = null;}try {context.unregisterReceiver(broadcastReceiver);} catch (Exception e) {e.printStackTrace();Log.i(TAG, "release: error:" + e.getMessage());}try {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) channel.close();} catch (Exception e) {e.printStackTrace();Log.i(TAG, "release:close channel error:" + e.getMessage());}}
}
udp 通讯类:
import android.util.Log;import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;public class SyncUDP implements Runnable {private static final String TAG = "ReceiveUDP";private Thread thread;private DatagramSocket socket;private OnUpdateListener listener;private int port;public void setListener(OnUpdateListener listener) {this.listener = listener;}public void release() {if (thread != null && !thread.isInterrupted())thread.interrupt();listener = null;closeSocket();if (thread != null) {try {thread.join();} catch (Exception e) {e.printStackTrace();}thread = null;}}public SyncUDP(int port) {this.port = port;thread = new Thread(this);thread.start();}public void sendAction(byte[] buf, String ip) {if (socket == null || socket.isClosed()) return;try {DatagramPacket sendPacket = new DatagramPacket(buf, buf.length);sendPacket.setAddress(InetAddress.getByName(ip));sendPacket.setPort(port);socket.send(sendPacket);} catch (Exception e) {e.printStackTrace();Log.i(TAG, "sendAction: send package error:" + e.getMessage());}}@Overridepublic void run() {while (!Thread.interrupted()) {try {byte[] by = new byte[16];socket = new DatagramSocket(port);socket.setBroadcast(true);while (!Thread.interrupted()) {try {// receive dataDatagramPacket receivePacket = new DatagramPacket(by, by.length);Log.i(TAG, "run: start wait package");// Join threadsocket.receive(receivePacket);String ip = receivePacket.getAddress().getHostAddress();Log.i(TAG, "run: get package len:" + receivePacket.getLength() + "; ip:" + ip);if (listener != null)listener.onUpdateUI(receivePacket.getData(), receivePacket.getLength(), ip);} catch (Exception e) {e.printStackTrace();break;}}closeSocket();} catch (Exception e) {e.printStackTrace();}}closeSocket();}private void closeSocket() {if (socket != null) {if (!socket.isClosed()) {try {socket.close();} catch (Exception e) {e.printStackTrace();}}socket = null;}}public interface OnUpdateListener {void onUpdateUI(byte[] buffer, int len, String ip);}
}
相关文章:

android wifi直连 wifip2pmanager
android wifi直连 wifip2pmanager;使用WiFi 直连,然后通过udp进行通讯。 Android WiFi 直连(Wi-Fi Direct,也称为Wi-Fi P2P)是一种让两台或多台设备通过Wi-Fi技术直接进行点对点连接的技术,无需借助传统的无…...

伸缩应用程序和执行滚动更新
📕作者简介: 过去日记,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。 📘相关专栏Rust初阶教程、go语言基础系列、spring教程等,大家有兴趣的可以看一看 📙Jav…...

解决WPS右键菜单冗余选项,去除WPS右键菜单选项
问题描述 安装WPS后,右键菜单会多出许多无用的选项,如何去除? 解决方法 按下WindowsS打开搜索栏,搜索配置工具打开 勾选所有的关闭和隐藏选项...

部署ELFK+zookeeper+kafka架构
目录 前言 一、环境部署 二、部署ELFK 1、ELFK ElasticSearch 集群部署 1.1 配置本地hosts文件 1.2 安装 elasticsearch-rpm 包并加载系统服务 1.3 修改 elasticsearch 主配置文件 1.4 创建数据存放路径并授权 1.5 启动elasticsearch是否成功开启 1.6 查看节点信息 …...

ActiveMQ 任意文件上传漏洞复现
一、使用弱口令登陆 访问 http://ip:8161/admin/ 进入admin登陆页面,使用弱口令登陆,账号密码皆为 admin,登陆成功后,headers中会出现验证信息 如: Authorization: Basic YWRtaW46YWRtaW4 # 二、利用PUT协议上…...

k8s实践总结
一、pod常用操作: 1、如何重启pod? 1.1 删除并重新创建Pod 这是最直接的方法。你可以通过kubectl命令行工具删除Pod,然后Kubernetes将基于其对应的Deployment、ReplicaSet或其他控制器自动重新创建它。 不建议并行删除全部pod,…...

前端从零到一搭建脚手架并发布到npm
这里写自定义目录标题 为什么需要脚手架?前置-第三方工具的使用1. 创建demo并运行-4步新建文件夹 zyfcli,并初始化npm init -y配置入口文件 2.commander-命令行指令3. chalk-命令行美化工具4. inquirer-命令行交互工具5. figlet-艺术字6. ora-loading工具…...

使用 git 提交项目到 github
文章推荐:https://zhuanlan.zhihu.com/p/193140870 连接失败:https://zhuanlan.zhihu.com/p/521340971 分支出错:https://blog.csdn.net/gongdamrgao/article/details/115032436...

SRE 与传统 IT 运营有何不同?
软件开发和部署方法的发展要求组织管理和维护 IT 基础设施的方式发生转变。站点可靠性工程(SRE) 是一门将软件工程的各个方面融入 IT 运营的学科,处于这一变革的前沿。随着专业人士和组织都寻求适应,对 SRE 认证和培训计划的需求激增。本博客探讨了 SRE …...

html公众号页面实现点击按钮跳转到导航
实现效果: 点击导航自动跳转到: html页面代码: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>跳转导航</title><meta name"keywords" conten…...

【算法】快速排序的基本思想、优化 | 挖坑填补法和区间分割法
创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡>𖥦<)!! 主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步! 更多算法分析与设计知识专栏:算法分析🔥 给大家跳…...

OSPF动态路由实验(华为)
思科设备参考:OSPF动态路由实验(思科) 一,技术简介 OSPF(Open Shortest Path First)是一种内部网关协议,主要用于在单一自治系统内决策路由。它是一种基于链路状态的路由协议,通过…...

EasyRecovery2024专业免费的电脑数据恢复软件
EasyRecovery数据恢复软件是一款功能强大的数据恢复工具,广泛应用于各种数据丢失场景,帮助用户从不同类型的存储介质中恢复丢失或删除的文件。 该软件支持恢复的数据类型非常广泛,包括但不限于办公文档、图片、音频、视频、电子邮件以及各种…...

Vue集成PageOffice实现在线编辑word、excel(前端配置)
一、什么是PageOffice PageOffice是一款在线的office编辑软件,帮助Web应用系统或Web网站实现用户在线编辑Word、Excel、PowerPoint文档。可以完美实现在线公文流转,领导批阅,盖章。可以给文件添加水印,在线安全预览防止用户下载…...

IBM SPSS Statistics for Mac:数据分析的卓越工具
IBM SPSS Statistics for Mac是一款功能强大的数据分析软件,专为Mac用户设计,提供了一系列专业的统计分析和数据管理功能。无论是科研人员、数据分析师还是学生,都能从中获得高效、准确的数据分析支持。 IBM SPSS Statistics for Mac v27.0.1…...

python爬虫------- Selenium下篇(二十三天)
🎈🎈作者主页: 喔的嘛呀🎈🎈 🎈🎈所属专栏:python爬虫学习🎈🎈 ✨✨谢谢大家捧场,祝屏幕前的小伙伴们每天都有好运相伴左右,一定要天天…...

获取字符串的全排列(去除字符串中2个字符相同时造成的重复)
一、概念 现有一个字符串,要打印出该字符串中字符的全排列。 以字符串abc为例,输出的结果为:abc、acb、bac、bca、cab、cba。 以字符串aab为例,输出的结果为:aab、aba、baa。 二、代码 public class Permutation {pub…...

HTML5新增的多媒体标签
在网页中加入音乐 <audio></audio> src 设置音乐文件名以及路径,<audio>标记支持MP3、WAV及OGG 3种音乐格式 autoplay:是否自动播放,加入autopaly属性表示自动播放 controls: 是否显示播放面板,加入controls属性表示显示播放面板 …...

温湿度传感器(DHT11)以及光照强度传感器(BH1750)的使用
前言 对于一些单片机类的环境检测或者智能家居小项目中,温湿度传感器(DHT11)以及光照强度传感器(BH1750)往往是必不可少的两个外设,下面我们来剖析这两个外设的原理,以及使用。 1. 温湿度传感…...

ActiveMQ 04 Linux下安装
Active MQ 04 Linux下安装 下载 解压 在init.d下建立软连接 ln -s /usr/local/activemq/bin/activemq ./设置开启启动 chkconfig activemq on 服务管理 service activemq start service activemq status service activemq stopNIO配置 默认配置为tcp,使用的…...

.pyc 文件是什么?是否有必要同步到 GitHub 远程仓库?
git status 时发现有很多 .pyc 的没有被 add (env) username:~/path/to/project$ git status On branch main Your branch is up to date with origin/main.Changes to be committed:(use "git restore --staged <file>..." to unstage)new file: xxx.pyCha…...

Zookeeper的集群搭建和ZAB协议详解
Zookeeper的集群搭建 1)zk集群中的角色 Zookeeper集群中的节点有三个角色: Leader:处理集群的所有事务请求,集群中只有一个LeaderFollwoer:只能处理读请求,参与Leader选举Observer:只能处理读…...

STM32 MPU配置参数
TXE LEVEL一般只用MPU_TEX_LEVEL0 1 - 1 - 1 -0性能最强(TEX - C - B- S). #define MPU_TEX_LEVEL0 ((uint8_t)0x00) #define MPU_TEX_LEVEL1 ((uint8_t)0x01) #define MPU_TEX_LEVEL2 ((uint8_t)0x02) 基于上表进行常用配置 ÿ…...

Kafka概述
目录 1、为什么需要消息队列(MQ) 2、使用消息队列的好处 3、消息队列的两种模式 4、Kafka 定义 5、Kafka 简介 6、Kafka 的特性 7、Kafka 系统架构 8、Partation 数据路由规则 9、分区的原因 1、为什么需要消息队列(MQ) …...

OpenHarmony编译构建系统
这篇来聊聊OpenHarmony的编译构建,经过前面的实践,再来看编译构建。 编译构建概述 在官网中提到了,OpenHarmony编译子系统是以GN和Ninja构建为基座,对构建和配置粒度进行部件化抽象、对内建模块进行功能增强、对业务模块进行功能…...

Qt5 编译oracle数据库驱动
库文件 1、Qt源码目录:D:\Qt5\5.15.2\Src\qtbase\src\plugins\sqldrivers\oci 2、oracle客户端SDK: https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html 下载各版本中的如下压缩包,一定要版本相同的 将两个压缩包…...

UE5学习日记——实现自定义输入及监听输入,组合出不同的按键输入~
UE5的自定义按键和UE4有所不同,在这里记录一下。 本文主要是记录如何设置UE5的自定义按键,重点是学会原理,实际开发时结合实际情况操作。 输入映射 1. 创建输入操作 输入操作并不是具体的按键映射,而是按键的激活方式࿰…...

为什么把script标签放在div下面?
放在底部可以优先加载页面的内容结构,提升页面渲染速度。只有等到HTML解析完成后,才会开始执行main.js,避免JS阻塞页面解析, 同时main.js里可能会操作DOM,如果放头部,可能会找不到节点而报错 <body><div id"root"><App></App>&l…...

Git 自定义命令
前言 在使用 hexo 搭建个人博客时,共两种部署的方法。分别为: 本地利用 hexo 的插件 hexo-deployer-git 来实现部署,缺点是需要多敲几个命令行且不方便对源码进行云端备份使用 Github Action 的 workflow 自动化部署,优势就是可…...

SpringBoot多数据源配置及使用
1.application.properties数据配置 首先现在配置文件中定义三个数据库相关信息 # 数据库1 targetLibraryMain.datasource.url jdbc:kingbase8://127.0.0.1:54321/DATA_ONE?useUnicodetrue&characterEncodingutf8&serverTimezoneGMT%2B8&allowMultiQueriestrue …...