Wi-Fi直连分享:Android设备间的高速连接

Wi-Fi直连分享:Android设备间的高速连接
引言
随着无线局域网(Wi-Fi)的普及和发展,使用Wi-Fi直连技术(P2P)在没有中间接入点的情况下实现设备间直接互联成为可能。通过Wi-Fi直连,具备相应硬件的Android 4.0及更高版本设备可以实现高速连接通信,比传统蓝牙连接具有更远的传输距离。这项技术对于多人游戏、照片共享等需要设备间数据共享的应用非常有用。
Wi-Fi直连的核心API是WifiP2pManager类。
普通连接,代码实现
初始化
private WifiP2pManager.Channel mChannel; // app与framework联系的纽带
private WifiP2pManager mManager;
...
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
创建群组
只有服务端设备需要执行此步骤,客户端设备可以跳过。即使不创建群组,设备仍然可以进行后续的设备发现和连接操作。一旦连接成功,这两台设备将自动形成一个群组,并在其中选择一台设备作为群主。创建群组后,会在Wi-Fi列表中出现一个名为DIRECT_**_DeviceName的网络,这个网络是为没有Wi-Fi直连功能的设备准备的,它们可以通过连接此网络来加入群组。但是使用此方式加入的设备不会收到WIFI_P2P_CONNECTION_CHANGED_ACTION广播,不过在调用mManager.requestGroupInfo时,可以获取到这些设备的信息。
mManager.createGroup(mChannel, new WifiP2pManager.ActionListener() {@Overridepublic void onSuccess() {appendLog("创建群组成功");// 在这里可以创建ServerSocket并等待客户端接入...}@Overridepublic void onFailure(int reason) {appendLog("创建群组失败");...}
});
很多地方都会使用到WifiP2pManager.ActionListener回调,下面列出了一些可能的错误原因:
/*** Wi-Fi直连操作失败*/
public static final int ERROR = 0;/*** 设备不支持Wi-Fi直连功能*/
public static final int P2P_UNSUPPORTED = 1;/*** 操作失败,框架忙于处理其他请求*/
public static final int BUSY = 2;/*** 操作失败,未添加任何服务请求*/
public static final int NO_SERVICE_REQUESTS = 3;
发现设备
mManager.discoverPeers(mChannel, mActionListener);
客户端设备直接执行此操作,不需要创建群组。两台设备必须同时执行设备发现操作,才能相互发现对方的存在。
停止发现设备
mManager.stopPeerDiscovery(mChannel, mActionListener);
连接设备
连接设备的操作可以由服务端或客户端发起。device是通过设备发现获得的对方设备信息,后续会介绍广播的相关内容。
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
mManager.connect(mChannel, config, mActionListener);
取消连接
连接后也可以取消连接。注意:取消操作将取消所有正在发起连接邀请的设备,不能针对单个设备进行操作。
mManager.cancelConnect(mChannel, mActionListener);
解散群组
当需要取消某个单一连接时,只能从客户端取消对服务端的连接。如果需要取消所有连接,只能通过解散群组来实现。
mManager.removeGroup(mChannel, mActionListener);
获取群组相关信息
可以通过以下代码获取群组中的所有设备信息:
mManager.requestGroupInfo(mChannel, new WifiP2pManager.GroupInfoListener() {@Overridepublic void onGroupInfoAvailable(WifiP2pGroup group) {appendLog("已连接的设备:");Collection<WifiP2pDevice> devices = group.getClientList();int i=1;for(WifiP2pDevice d: devices) {appendLog((i++) +": ip:" +d.deviceAddress+", name:" +d.deviceName +", isGroupOwner:" +d.isGroupOwner() );}}
});
广播实现
使用广播来通知应用层自身设备、发现设备和连接设备的状态变化。
| Intent | 说明 |
|---|---|
WIFI_P2P_CONNECTION_CHANGED_ACTION | 当设备的 WLAN 连接状态更改时广播。 |
WIFI_P2P_PEERS_CHANGED_ACTION | 当您调用 discoverPeers() 时广播。如果您在应用中处理此 Intent,则通常需要调用 requestPeers() 以获取对等设备的更新列表。 |
WIFI_P2P_STATE_CHANGED_ACTION | 当 WLAN P2P 在设备上启用或停用时广播。 |
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION | 当设备的详细信息(例如设备名称)更改时广播。 |
WIFI_P2P_DISCOVERY_CHANGED_ACTION | 当设备开始或停止发现设备时广播 |
下面是一个实现广播接收器的示例:
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {public WiFiDirectBroadcastReceiver() {super();}@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {// 检查 Wi-Fi 是否启用并通知相应的活动int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, WifiP2pManager.WIFI_P2P_STATE_DISABLED);// wifi p2p 能否使用取决于你的 Wi-Fi 是否已打开。if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {// wifi p2p 可用} else if (state == WifiP2pManager.WIFI_P2P_STATE_DISABLED) {// wifi p2p 不可用}} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {// 调用 WifiP2pManager.requestPeers() 获取当前对等设备列表// 获取所有扫描到的设备。WifiP2pDeviceList mPeers = intent.getParcelableExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST);} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {// 处理新连接或断开连接的情况// wifi p2p 连接状态发生变化,在创建组成功时也会触发该广播。// 获取 Wi-Fi P2P 网络状态NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);// 关于该群组的连接信息。有三个属性:// 1. groupFormed:群组是否已形成,作为群主,创建群组后获得的该属性值为 true// 2. isGroupOwner:本设备是否为群主// 3. groupOwnerAddress:群主的 IP 地址WifiP2pInfo p2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);// 群组的相关信息,如网络名称、密码和所有已连接设备等。WifiP2pGroup p2pGroup = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);if (networkInfo != null && networkInfo.isConnected()) {// 表明已连接上,创建组成功也会进入该判断if (p2pInfo.groupFormed && p2pInfo.isGroupOwner) {// 群组已形成,且本设备为群主} else if (p2pInfo.groupFormed) {// 群组已形成,但本设备非群主// 获取群主 IPString groupOwnerAddress = p2pInfo.groupOwnerAddress.getHostAddress();// 建立 Socket 连接}}} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {// 处理本设备的 Wi-Fi 状态变化// 本设备信息发生变化WifiP2pDevice wifiP2pDevice = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);} else if (WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)) {// 处理发现设备操作状态变化// WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED:停止状态// WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED:开始状态int discoveryState = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE,WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED);}}
}
获取连接信息
上述代码片段展示了如何使用WifiP2pManager来获取连接信息。通过调用requestConnectionInfo()方法,并传入一个ConnectionInfoListener,我们可以在连接信息可用时得到回调。
- 如果连接信息为null或群主地址为空,直接返回。
- 如果群已建立,且设备是群主,可以通过
requestGroupInfo()方法获取群组信息,其中包括WiFi热点密码。
对于客户端设备,可以根据需要执行相应的操作。
针对性WiFi P2P连接
除了普通的搜索和连接方式外,还可以使用WifiP2pManager.discoverServices()方法进行针对性的WiFi P2P连接。这种方式会根据服务提供的字段和协议来判断是否符合连接要求。
服务创建
-
Bonjour
使用Bonjour服务时,可以通过创建txt记录来指定相关信息。
示例代码如下:
Map<String, String> txtRecord = new HashMap<String, String>(); txtRecord.put("txtvers", "1"); txtRecord.put("pdl", "application/postscript"); mServiceInfo = WifiP2pDnsSdServiceInfo.newInstance(instanceName,serviceType, txtRecord);其中,
serviceType参数指定了应用程序使用的协议和传输层。 -
UPnP
使用UPnP服务时,可以指定服务类型和相关信息。
示例代码如下:
List<String> services = new ArrayList<String>(); services.add("urn:schemas-upnp-org:service:AVTransport:1"); services.add("urn:schemas-upnp-org:service:ConnectionManager:1"); mServiceInfo = WifiP2pUpnpServiceInfo.newInstance("6859dede-8574-59ab-9332-123456789011","urn:schemas-upnp-org:device:MediaRenderer:1",services);
添加服务
创建完服务信息后,可以使用addLocalService()方法将服务添加到本地。
示例代码如下:
mManager.addLocalService(mChannel, mServiceInfo, mActionListener);
创建群组
与之前的示例相同,可以使用相同的方法来创建WiFi P2P群组。
创建服务监听
针对Bonjour和UPnP服务,可以分别创建相应的监听器。当搜索到设备服务时,这些监听器会得到回调。
示例代码如下:
// Bonjour服务监听器
WifiP2pManager.DnsSdServiceResponseListener ptrListener = new WifiP2pManager.DnsSdServiceResponseListener() {@Overridepublic void onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice srcDevice) {}}WifiP2pManager.DnsSdTxtRecordListener txtListener = new WifiP2pManager.DnsSdTxtRecordListener() {@Overridepublic void onDnsSdTxtRecordAvailable(String fullDomainName, Map<String, String> txtRecordMap, WifiP2pDevice srcDevice) {}
}
mManager.setDnsSdResponseListeners(mChannel, ptrListener, txtListener);// UPnP服务监听器
private WifiP2pManager.UpnpServiceResponseListener upnpListener = new WifiP2pManager.UpnpServiceResponseListener() {@Overridepublic void onUpnpServiceAvailable(List<String> uniqueServiceNames, WifiP2pDevice srcDevice) {}
}
mManager.setUpnpServiceResponseListener(mChannel, upnpListener);
这些监听器会在搜索到设备服务时得到回调。根据搜索时传入的服务request,决定回调哪个监听器。
发现服务
通过创建相应的服务请求,可以发现Bonjour和UPnP服务。
示例代码如下:
// Bonjour类型的TXT服务,对应上面 txtListener
WifiP2pDnsSdServiceRequest txtRequest = WifiP2pDnsSdServiceRequest.newInstance(INSTANCE_NAME, SERVICE_TYPE);
// Bonjour类型的PTR服务,对应上面 ptrListener
WifiP2pDnsSdServiceRequest ptrRequest = WifiP2pDnsSdServiceRequest.newInstance(SERVICE_TYPE);
// UPnP服务,对应上面的upnpListener
WifiP2pUpnpServiceRequest upnpRequest = WifiP2pUpnpServiceRequest.newInstance(searchTarget);mManager.addServiceRequest(mChannel, txtRequest, mActionListener);
mManager.addServiceRequest(mChannel, ptrRequest, mActionListener);
mManager.addServiceRequest(mChannel, upnpRequest, mActionListener);
其余步骤与之前的示例相同。
以上是针对性WiFi P2P连接的示例代码和步骤。你可以根据自己的需求来选择合适的服务类型和设置相应的监听器来处理搜索到的设备服务。
参考
参考文档:https://developer.android.google.cn/guide/topics/connectivity/wifip2p?hl=zh-cn
相关文章:
Wi-Fi直连分享:Android设备间的高速连接
Wi-Fi直连分享:Android设备间的高速连接 引言 随着无线局域网(Wi-Fi)的普及和发展,使用Wi-Fi直连技术(P2P)在没有中间接入点的情况下实现设备间直接互联成为可能。通过Wi-Fi直连,具备相应硬件…...
LeetCode 面试题 05.06. 整数转换
文章目录 一、题目二、Java 题解 一、题目 整数转换。编写一个函数,确定需要改变几个位才能将整数A转成整数B。 示例1: 输入: A 29 (或者0b11101), B 15(或者0b01111) 输出: 2 示例2: 输入&a…...
增强for循环和一般for循环的对比使用
文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。个人B站主页热爱技术的小郑 ,视频内容主要是对应文章的视频讲解形式。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘…...
云原生之使用Docker部署RSS阅读器Huntly
云原生之使用Docker部署RSS阅读器Huntly 一、Huntly介绍1.1 Huntly简介1.2 Huntly功能2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载Huntly镜像五、部署Huntly5.1 创建挂载目录5.2 创建Hun…...
Powershell 实现禁用密码复杂性,空密码
前提条件 开启wmi,配置网卡,参考 实现一键关闭密码策略和远程空密码登录 最近客户需要的一个无法理解的需求,需要远程登录不输入密码,安全性没有了还要实现,没办法客户是上帝,客户怎么开心怎么来都行,安全性问题告知不重视,实际环境不建议一下操作,只要联网你被黑的哦…...
【c语言】详解动态内存管理
目录 关于动态内存分配malloc和calloc函数介绍动态内存回收----freerealloc函数介绍常见的动态内存错误 关于动态内存分配 回想一下我们之前学过的内存开辟方式: int val 20;//在栈空间上开辟四个字节 char arr[10] {0};//在栈空间上开辟10个字节的连续空间在学…...
深度学习概念——端对端
目录 1、端对端是什么2、端对端有什么用3、例子4、引用 在读论文的过程中反复遇到端对端的概念,就需要理解深刻一些。在此将收集到的一些资料拿出来辅以自己的拙见,请大家多多批评指正! 1、端对端是什么 在计算机学科中有一种算法叫分治法&a…...
苹果触控笔有必要买吗?平价ipad电容笔推荐
其实,市面上的数码类产品很多,有的侧重于美观,有的侧重于功能,有的侧重于性能。与iPad平板电脑搭配使用的电容笔同样也如此。因此,在选购电容笔时,一定要了解有关电容笔的知识。在购买之前,一定…...
React的高阶函数
1.认识高阶函数 高阶组件 本身不是一个组件,而是一个函数函数的参数是一个组件,返回值也是一个组件 高阶组件的定义 import ThemeContext from "../context/theme_context"function withTheme(OriginComponent) {return (props) > {retur…...
Java8实战-总结34
Java8实战-总结34 重构、测试和调试使用 Lambda 重构面向对象的设计模式观察者模式责任链模式 重构、测试和调试 使用 Lambda 重构面向对象的设计模式 观察者模式 观察者模式是一种比较常见的方案,某些事件发生时(比如状态转变)࿰…...
uniapp项目实践总结(二十四)安卓平台 APP 打包教程
导语:当你的应用程序开发完成后,在上架安卓应用商店之前,需要进行打包操作,下面简单介绍一下打包方法。 目录 准备工作配置项目生成证书打包配置准备工作 在打包之前,请保证你的 uniapp 应用程序编译到安卓手机模拟器的 App 是可以正常运行的,APP 打包分为安卓和 ios 两…...
GeoServer地图服务器权限控制
目录 1下载相关软件 2部署软件 3配置鉴权环节 4Java工程 5测试鉴权 6测试鉴权结果分析 本文章应该会后面试验一个鉴权功能就会发布一系列测试过程(GeoServer有很多鉴权方式) 1Download - GeoServer 1下载相关软件 进入geoserver官网的下载页面 …...
Python+requests+unittest+excel实现接口自动化测试框架
一、框架结构: 工程目录 二、Case文件设计 三、基础包 base 3.1 封装get/post请求(runmethon.py) 1 import requests2 import json3 class RunMethod:4 def post_main(self,url,data,headerNone):5 res None6 if heade…...
25807-2020 间脲基苯胺盐酸盐 课堂随笔
声明 本文是学习GB-T 25807-2020 间脲基苯胺盐酸盐. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了间脲基苯胺盐酸盐的要求、采样、试验方法、检验规则以及标志、标签、包装、运输和 贮存。 本标准适用于间脲基苯胺盐酸盐产品…...
苹果手机通讯录联系人如何一键删除? 1个方法轻松解决!
手机通讯录里存了上百个之前公司客户的电话,结果苹果手机不支持一键清空联系人。有什么其他办法可以将这些联系人一次性全部删除吗? 随着时间的增长,手机通讯录中难免会积累许多不再联系的用户或者是已经失效的联系人。对于这些许久不联系的人…...
【Linux成长史】Linux编辑器-gcc/g++使用
🎬 博客主页:博主链接 🎥 本文由 M malloc 原创,首发于 CSDN🙉 🎄 学习专栏推荐:LeetCode刷题集 数据库专栏 初阶数据结构 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如…...
【CNN-FPGA开源项目解析】卷积层03--单格乘加运算单元PE 单窗口卷积块CU 模块
03–单格乘加运算单元PE & 单窗口卷积块CU 文章目录 03--单格乘加运算单元PE & 单窗口卷积块CU前言单格乘加运算单元PE代码模块结构时序逻辑分析对其上层模块CU的要求 单窗口卷积块CU代码逻辑分析 前言 第一和第二篇日志已经详细阐述了"半精度浮点数"的加…...
一文教你学会ArcGIS Pro地图设计与制图系列全流程(2)
ArcGIS Pro做的成果图及系列文章目录: 系列文章全集: 《一文教你学会ArcGIS Pro地图设计与制图系列全流程(1)》《一文教你学会ArcGIS Pro地图设计与制图系列全流程(2)》《一文教你学会ArcGIS Pro地图设计与…...
ICML 2017: 基于卷积的Seq2Seq解决方案
一.文章概述 通常而言,Seq2Seq解决方案一般都采用循环神经网络,但在本文,作者提出了基于卷积神经网络的解决方案ConvS2S。基于卷积神经网络的方案有两大优势:计算并行化更高,优化更容易(非线性的数量是固定…...
探索GmSSL+Nginx实践及原理
前言 随着大国崛起步伐的迈进,敏感单位的数据安全问题越发受到重视,数据的加密安全传输尤为重要,对于安全问题,国家自研加密算法提供了有力的保障。 作为信创行业的国有企业,十分有必要在网络通信中使用国密算法加密…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
