Android 设备通过WIFI传输数据 - 点对点传输
点对点传输(P2P)又是WLAN直连,他可以在没有中间接入点的情况下,通过 WLAN 进行直接互联。他有用户介入操作少,比蓝牙传输速度高等特点,对设备的要求仅仅为14,同时他又不占用wlan0网卡。
WLAN P2P 需要使用到 WifiP2pManager ,同时需要以下权限,这里面有一些是运行时权限,需要用户同意后才能使用。
<uses-sdk android:minSdkVersion="14" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
点对点传输(P2P)至少有两个有Wifi的设备,其中一个是Android,首先确定Android设备和另外一个设备是否支持P2P连接。把手机连接电脑运行 adb shell ip addr|grep p2p0 -A2
有输出就带边可以使用,一般来说都可以使用。
29: p2p0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000link/ether 02:00:2d:63:a5:6b brd ff:ff:ff:ff:ff:ff
注意看上面的输出,link/ether 02:00:2d:63:a5:6
为p2p的Mac地址,不同的设备之间使用Mac地址连接,所以首先要知道P2P(p2p0)的Mac地址,这个和wifi(wlan0)的地址不是同一个,在代码中需要使用下面方法获取。
public static String getLocalMacAddress() {try {List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());for (NetworkInterface ntwInterface : interfaces) {if (ntwInterface.getName().equalsIgnoreCase("p2p0")) {byte[] byteMac = ntwInterface.getHardwareAddress();if (byteMac == null) {return null;}StringBuilder strBuilder = new StringBuilder();for (int i = 0; i < byteMac.length; i++) {strBuilder.append(String.format("%02X:", byteMac[i]));}if (strBuilder.length() > 0) {strBuilder.deleteCharAt(strBuilder.length() - 1);}return strBuilder.toString();}}} catch (Exception e) {Log.d("Lecon", e.getMessage());}return null;
}
接下来看一下如何主动连接到p2p设备。
使用方法
首先通过 WifiP2pManager 的initialize初始化。
val manager: WifiP2pManager? by lazy(LazyThreadSafetyMode.NONE) {getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager?
}override fun onCreate(savedInstanceState: Bundle?) {mChannel = manager?.initialize(this, mainLooper, null)
}
同时使用广播来接受各种P2P连接的状态变化。
var mChannel: WifiP2pManager.Channel? = null
var mReceiver: WiFiDirectBroadcastReceiver? = nullprivate val mWifiP2pManager: WifiP2pManager by lazy(LazyThreadSafetyMode.NONE) {getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager
}private val mIntentFilter: IntentFilter by lazy(LazyThreadSafetyMode.NONE) {IntentFilter().apply {addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION)}
}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)mChannel = mWifiP2pManager.initialize(this, mainLooper, null)mReceiver = WiFiDirectBroadcastReceiver(mWifiP2pManager, mChannel, this)
class WiFiDirectBroadcastReceiver(private val mManager: WifiP2pManager?,private val mChannel: WifiP2pManager.Channel?,private val mActivity: MainActivity
) : BroadcastReceiver() {override fun onReceive(context: Context, intent: Intent) {val action = intent.actionif (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION == action) {// 当 WLAN P2P 在设备上启用或停用时广播} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION == action) {// 调用 requestPeers() 方法,以获得当前所发现对等设备的列表。// 同时 在这里调用 connect 方法连接对方机器} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION == action) {// 当设备的 WLAN 连接状态更改时广播。// 连接对方机器成功或者失败都会在这里回调} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION == action) {// 当设备的详细信息(例如设备名称)更改时广播}
}
上边哪一些代码可以当成主动发起扫描之后的回调,使用广播进行回调说起来真的是挺复杂的,但是仔细想想,操作硬件设备本来就是跨进程的,而且这个还是长时间耗时操作,系统通过广播回调也是合理的。
到现在位置,可以把以上代码运行到Android上,他就可以最为P2P连接的被连接端。
连接到设备
连接到设备的时候,首先要确定对方设备的mac地址,上面的两种方法是针对于Android设备的。一种是adb方式,一种是代码获取。
接下来要发现设备:
mWifiP2pManager.discoverPeers(mChannel, object : WifiP2pManager.ActionListener {override fun onSuccess() {Toast.makeText(this@MainActivity, "已发现设备,准备连接", Toast.LENGTH_SHORT).show()}override fun onFailure(reasonCode: Int) {}
})
返现设备之后,通过广播回调的 WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION 事件获取设备列表。找到列表中的设备与被连接设备mac地址一致的,确保我们被连接机器已经就绪。
mManager?.requestPeers(mChannel) { peers ->for (device in peers.deviceList) {if (mac != null && mac.equals(device.deviceAddress, ignoreCase = true)) {connectToDevice(device)}}
}
接下来就可以连接设备了!
val config = WifiP2pConfig()
config.deviceAddress = "被连接设备的Mac地址"
mManager?.connect(mChannel, config, object : WifiP2pManager.ActionListener {override fun onSuccess() {Toast.makeText(mActivity, "连接成功", Toast.LENGTH_SHORT).show()}override fun onFailure(reason: Int) {}
})
如果被连接设备是Android,你应该能看到一个连接提示,点击接受这样两台设备之间就连接成功了,通过WIFI两个设备可以实现近场通讯。
通信
通信之前需要知道被连接设备的ip地址。如果是android设备,在被连接设备执行adb shell ip addr|grep p2p0 -A4
就可以看到,这也是检测是否连接成功的方法。代码获取仍然要获取p2p0网卡的,wlan0获取的ip地址不能用于这里。
public static String getLocalIp() {try {List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());for (NetworkInterface intf : interfaces) {if (!intf.getName().contains("p2p0"))continue;List<InetAddress> addrs = Collections.list(intf.getInetAddresses());for (InetAddress addr : addrs) {if (!addr.isLoopbackAddress()) {return addr.getHostAddress().toUpperCase();}}}} catch (Exception ex) {ex.printStackTrace();}return "";
}
如果被连接设备是一台服务器(在Android里面搭建一台服务器也是可以的),在这台设备上可以用okhttp等框架进行网络访问,或者使用socket进行传输。
现在两个手机(P2P)设备之间就可以同过WLAN直接通信了。
下面是源代码:https://github.com/leconio/WifiDircetP2PDemo
Android 设备通过WIFI传输数据 - 点对点传输相关推荐
- 获取Android 设备的WIFI IPv4地址
一.前言 有时候需要获取Android设备的IPv4地址,可以通过下面列出的一种方法获取. 二.获取方法 // 获取IPv4地址private String getDeviceIPv4() {//获取 ...
- 使用iperfjperf测试Android设备的wifi速率方法
测试设备:PC电脑,路由器,安卓设备 测试工具软件:iperf和jperf 测试方法使用到两个软件:jperf实际为iperf的图形化程序,因为使用到PC,所以用jperf比较方便.而Android设 ...
- android设备获取wifi和蓝牙状态并进行打开或关闭操作
wifi 获取系统wifi服务: WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Co ...
- 通过wifi连接android设备的方法
最近由于要在另外一台android设备上调试代码,在本机PC上查看其log.两台机器离的比较远, 无法用usb直接连接,于是在网上找了很多资料,最找使用adb connect方法解决了该问题.解决过程 ...
- adb通过wifi连接android设备(魅族note3)
AS使用usb数据线调试手机时有时一松碰一下就断了,所以尝试用无线调试会稳定一点. 1.首先安装ADB WIFI 打开FILE->Settings->Plugins->Browse ...
- esc pos命令 java使用_18、ESC/POS指令集在android设备上使用实例(通过socket)
网上关于通过android来操作打印机的例子太少了,为了方便更多的开发同仁,将近日所学分享一下. 我这边是通过android设备通过无线来对打印机(佳博58mm热敏式-58130iC)操作,实现餐厅小 ...
- Android手机用wifi连接adb调试的方法
https://www.jianshu.com/p/dc6898380e38 0x0 前言 Android开发肯定要连接pc的adb进行调试,传统的方法是用usb与pc进行连接,操作简单即插即用,缺点 ...
- Android 9.0 WiFi BG Scan机制
欢迎大家一起学习探讨通信之WLAN.本节我们讨论关于Android设备的WiFi Background 扫描机制.通过使用WiFi设备的经验可知.WiFi设备连接上WiFi网络,必要条件是需要扫描到目 ...
- 连接android设备
一,WIFI连接 1,将android设备接入wifi 2,查看设备IP:设置-->无线和网络-->WLAN-->WLAN设置(在右上角)-->IP地址 :192.168.13 ...
最新文章
- 基于redis AE异步网络架构
- 离线轻量级大数据平台Spark之MLib机器学习库Word2Vec实例
- Lighting System Design UVA - 11400 动态规划
- php表单写入数据库,php表单写入数据库
- 授人以鱼不如授人以渔——CPU漏洞的Symantec解决之道
- vscode 使用笔记
- Self Attention和Multi-Head Attention的原理和实现
- [HTTP] HTTP各种特性总览
- 适用于 Windows PowerShell 的 SMS Cmdlet
- BootStrap的基本使用
- 计算机安装重装出现错误,一键重装失败怎么办?电脑重装系统失败的原因和解决方法...
- MAC IDEA常用快捷键
- 错误 E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
- 之前用Delphi随手写的软键盘SoftKeyBoard
- windows替换鼠标指针
- C语言实现创建游戏角色(包含文件写入)
- 【开始报名】第二届中国移动“梧桐杯”大数据应用创新大赛邀你夺52w大奖
- 马克思 第一章 世界的物质性及其发展规律
- Python+selenium+360浏览器实现自动测试
- UI基础三:简单的BOL报表开发