当前位置: 首页 > news >正文

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&#xff1b;使用WiFi 直连&#xff0c;然后通过udp进行通讯。 Android WiFi 直连&#xff08;Wi-Fi Direct&#xff0c;也称为Wi-Fi P2P&#xff09;是一种让两台或多台设备通过Wi-Fi技术直接进行点对点连接的技术&#xff0c;无需借助传统的无…...

伸缩应用程序和执行滚动更新

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d8;相关专栏Rust初阶教程、go语言基础系列、spring教程等&#xff0c;大家有兴趣的可以看一看 &#x1f4d9;Jav…...

解决WPS右键菜单冗余选项,去除WPS右键菜单选项

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

部署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登陆页面&#xff0c;使用弱口令登陆&#xff0c;账号密码皆为 admin&#xff0c;登陆成功后&#xff0c;headers中会出现验证信息 ​ 如&#xff1a; Authorization: Basic YWRtaW46YWRtaW4 # 二、利用PUT协议上…...

k8s实践总结

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

前端从零到一搭建脚手架并发布到npm

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

使用 git 提交项目到 github

文章推荐&#xff1a;https://zhuanlan.zhihu.com/p/193140870 连接失败&#xff1a;https://zhuanlan.zhihu.com/p/521340971 分支出错&#xff1a;https://blog.csdn.net/gongdamrgao/article/details/115032436...

SRE 与传统 IT 运营有何不同?

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

html公众号页面实现点击按钮跳转到导航

实现效果&#xff1a; 点击导航自动跳转到&#xff1a; html页面代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>跳转导航</title><meta name"keywords" conten…...

【算法】快速排序的基本思想、优化 | 挖坑填补法和区间分割法

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法分析与设计知识专栏&#xff1a;算法分析&#x1f525; 给大家跳…...

OSPF动态路由实验(华为)

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

EasyRecovery2024专业免费的电脑数据恢复软件

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

Vue集成PageOffice实现在线编辑word、excel(前端配置)

一、什么是PageOffice PageOffice是一款在线的office编辑软件&#xff0c;帮助Web应用系统或Web网站实现用户在线编辑Word、Excel、PowerPoint文档。可以完美实现在线公文流转&#xff0c;领导批阅&#xff0c;盖章。可以给文件添加水印&#xff0c;在线安全预览防止用户下载…...

IBM SPSS Statistics for Mac:数据分析的卓越工具

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

python爬虫------- Selenium下篇(二十三天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…...

获取字符串的全排列(去除字符串中2个字符相同时造成的重复)

一、概念 现有一个字符串&#xff0c;要打印出该字符串中字符的全排列。 以字符串abc为例&#xff0c;输出的结果为&#xff1a;abc、acb、bac、bca、cab、cba。 以字符串aab为例&#xff0c;输出的结果为&#xff1a;aab、aba、baa。 二、代码 public class Permutation {pub…...

HTML5新增的多媒体标签

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

温湿度传感器(DHT11)以及光照强度传感器(BH1750)的使用

前言 对于一些单片机类的环境检测或者智能家居小项目中&#xff0c;温湿度传感器&#xff08;DHT11&#xff09;以及光照强度传感器&#xff08;BH1750&#xff09;往往是必不可少的两个外设&#xff0c;下面我们来剖析这两个外设的原理&#xff0c;以及使用。 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&#xff0c;使用的…...

.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&#xff09;zk集群中的角色 Zookeeper集群中的节点有三个角色&#xff1a; Leader&#xff1a;处理集群的所有事务请求&#xff0c;集群中只有一个LeaderFollwoer&#xff1a;只能处理读请求&#xff0c;参与Leader选举Observer&#xff1a;只能处理读…...

STM32 MPU配置参数

TXE LEVEL一般只用MPU_TEX_LEVEL0 1 - 1 - 1 -0性能最强&#xff08;TEX - C - B- S&#xff09;. #define MPU_TEX_LEVEL0 ((uint8_t)0x00) #define MPU_TEX_LEVEL1 ((uint8_t)0x01) #define MPU_TEX_LEVEL2 ((uint8_t)0x02) 基于上表进行常用配置 &#xff…...

Kafka概述

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

OpenHarmony编译构建系统

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

Qt5 编译oracle数据库驱动

库文件 1、Qt源码目录&#xff1a;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 下载各版本中的如下压缩包&#xff0c;一定要版本相同的 将两个压缩包…...

UE5学习日记——实现自定义输入及监听输入,组合出不同的按键输入~

UE5的自定义按键和UE4有所不同&#xff0c;在这里记录一下。 本文主要是记录如何设置UE5的自定义按键&#xff0c;重点是学会原理&#xff0c;实际开发时结合实际情况操作。 输入映射 1. 创建输入操作 输入操作并不是具体的按键映射&#xff0c;而是按键的激活方式&#xff0…...

为什么把script标签放在div下面?

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

Git 自定义命令

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

SpringBoot多数据源配置及使用

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