简介:WIFI是指应用无线通信技术将计算机设备互联起来,构成可以互相通信和实现资源共享的网络体系。
Android设备支持两种主要的无线网络连接方式:WiFi直连(Wi-Fi Direct)和普通WiFi。这两种方式的主要区别在于它们的连接方式和用途。
-
WiFi直连(Wi-Fi Direct) :
- 也被称为Wi-Fi P2P,是一种允许设备之间直接连接的技术,无需传统的无线路由器或接入点。
- 这种技术使得设备间可以快速建立安全的无线连接,实现文件传输、屏幕共享、游戏对战等多种应用,尤其适用于智能手机、平板电脑、打印机、相机等消费电子设备间的近距离通信。
- 在Android 4.0(API level 14)或更高版本中,WiFi直连作为一项功能被引入,允许设备在不通过互联网或移动网络的情况下直接相互通信。IOS好像是没有这功能。
-
普通WiFi:
- 这是通过无线路由器或接入点连接到互联网的标准方式。
- 用户需要通过输入无线网络名称(SSID)和密码来连接到这些网络,以便访问互联网资源。
API
| 方法 | 说明 |
|---|---|
| initialize() | 通过 WLAN 框架注册应用。必须先调用此方法,然后再调用任何其他 WLAN P2P 方法。 |
| connect() | 启动与具有指定配置的设备的对等连接。 |
| cancelConnect() | 取消任何正在进行的对等群组协商。 |
| requestConnectInfo() | 请求设备连接信息。 |
| createGroup() | 以群组所有者的身份,使用当前设备创建对等群组。 |
| removeGroup() | 移除当前对等群组。 |
| requestGroupInfo() | 请求对等群组信息。 |
| discoverPeers() | 启动对等设备发现 |
| requestPeers() | 请求已发现对等设备的当前列表。 |
ACTION
WLAN P2P 事件时会广播的 Intent,例如发现新的对等设备时,或设备的 WLAN 状态更改时。您可以通过创建处理这些 Intent 的广播接收器,在应用中注册接收这些 Intent:
| ACTION | 说明 |
|---|---|
| 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 | 当设备的详细信息(例如设备名称)更改时广播。 |
1.权限申请
<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" />
2.判断是否支持P2P,调用initialize初始化
private fun initP2p(): Boolean {
// Device capability definition check
if (!packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)) {
Log.e("TAG", "Wi-Fi Direct is not supported by this device.")
return false
}
// Hardware capability check
if (wifiManager == null) {
Log.e("TAG", "Cannot get Wi-Fi system service.")
return false
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (!wifiManager!!.isP2pSupported) {
Log.e("TAG", "Wi-Fi Direct is not supported by the hardware or Wi-Fi is off.")
return false
}
}
if (wifiP2pManager == null) {
Log.e("TAG", "Cannot get Wi-Fi Direct system service.")
return false
}
//初始化
channel = wifiP2pManager!!.initialize(this@DirectWifiActivity, mainLooper, null)
if (channel == null) {
Log.e("TAG", "Cannot initialize Wi-Fi Direct.")
return false
}
return true
}
3.注册广播
private fun receiveReigst() {
intentFilter = 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)
wifiP2pReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION == action) {
Log.i("tag", "当在设备上启用或停用 Wi-Fi 点对点时广播。")
val state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1)
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
// WiFi P2P is enabled
Log.i("tag", "状态改变 WiFi P2P is enabled")
//todo
//可搜索周围P2P设备 discoverPeers
} else {
// WiFi P2P is not enabled
Log.i("tag", "状态改变 WiFi P2P is not enabled");
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION == action) {
Log.i(
"tag",
"当您调用 discoverPeers() 时广播。如果您在应用中处理此 intent,则通常需要调用 requestPeers() 来获取更新后的对等设备列表。"
);
// Request available peers from the WifiP2pManager
if (currentDirectState != DIRECT_DISCOVER_SUCCESS) {
return
}
currentDirectState = DIRECT_REQUEST_PEER
requestPeers()
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION == action) {
Log.i(
"tag",
"表明Wi-Fi对等网络的连接状态发生了改变,应用可以使用 requestConnectionInfo()、requestNetworkInfo() 或 requestGroupInfo() 来检索当前连接信息。 "
);
// Respond to new connection or disconnections
if (currentDirectState != DIRECT_REQUEST_CONNECT_SUCCESS) {
Log.i("tag", "当前状态不需要请求连接信息")
return
}
requestConnectionInfo()
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION == action) {
Log.i("tag", "表明该设备的配置信息发生了改变");
val device: WifiP2pDevice? =
intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE)
Log.i(
"tag",
"本设备信息发生变化:" + device!!.deviceName + ", " + device.deviceAddress
)
requestDeviceInfo()
// Respond to this device's wifi state changing
}
}
}
registerReceiver(wifiP2pReceiver, intentFilter)
}
private fun requestDeviceInfo() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
this,
Manifest.permission.NEARBY_WIFI_DEVICES
) != PackageManager.PERMISSION_GRANTED
) {
return
}
wifiP2pManager!!.requestDeviceInfo(channel!!
) { p0 -> Log.i("tag", p0!!.toString()) }
}
}
4.发现可连接的对等设备,请调用 discoverPeers(),以检测范围内的可用对等设备。对此功能的调用为异步操作。 当应用接收到 WIFI_P2P_PEERS_CHANGED_ACTION Intent 时,您可以通过 requestPeers() 请求已发现对等设备的列表。以下代码展示如何完成此项设置:
private fun discoverPeers() {
// Check if location permission is granted
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION
),
PERMISSION_REQUEST_CODE
)
return
}
// Check if location service is enabled
if (!wifiManager!!.isWifiEnabled) {
Toast.makeText(this@DirectWifiActivity, "Please enable WiFi", Toast.LENGTH_SHORT).show()
val panelIntent = Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY)
val componentName = panelIntent.resolveActivity(packageManager)
if (componentName != null) {
startActivity(panelIntent)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startActivity(Intent(Settings.ACTION_WIFI_SETTINGS))
} else {
wifiManager!!.setWifiEnabled(true)//android Q 默认返回false
}
return
}
if (!isLocationEnabled()) {
Toast.makeText(this@DirectWifiActivity, "Please enable Location", Toast.LENGTH_SHORT)
.show()
startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS))
return
}
currentDirectState = DIRECT_DISCOVER_CONNECT
wifiP2pManager!!.discoverPeers(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
// Peers discovery initiated
currentDirectState = DIRECT_DISCOVER_SUCCESS
Toast.makeText(this@DirectWifiActivity, "Discovering peers", Toast.LENGTH_SHORT)
.show()
}
override fun onFailure(reason: Int) {
currentDirectState = DIRECT_DISCOVER_FAIL
Toast.makeText(
this@DirectWifiActivity,
"Failed to discover peers $reason",
Toast.LENGTH_SHORT
)
.show()
}
})
}
5.停止寻找
wifiP2pManager!!.stopPeerDiscovery(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Log.i("tag", "停止成功")
}
override fun onFailure(p0: Int) {
Log.i("tag", "停止成功")
}
})
6.请求WIFI列表数据
private fun requestPeers() {
if (ActivityCompat.checkSelfPermission(
this@DirectWifiActivity,
android.Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this@DirectWifiActivity,
arrayOf<String>(android.Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSION_REQUEST_CODE
)
return
}
wifiP2pManager!!.requestPeers(channel, peerListListener)
}
/**
* 收到的设备列表信息
*/
private val peerListListener = object : WifiP2pManager.PeerListListener {
@SuppressLint("NotifyDataSetChanged")
override fun onPeersAvailable(peers: WifiP2pDeviceList?) {
if (peers != null) {
val peerList = peers.deviceList
Log.i("tag", peerList.toString())
if (peerList.isNotEmpty()) {
if (deviceListAdapter == null) {
deviceListAdapter =
DeviceListAdapter(this@DirectWifiActivity, peerList.toList())
mBinding.recyclerView.layoutManager = LinearLayoutManager(
this@DirectWifiActivity,
LinearLayoutManager.VERTICAL,
false
)
mBinding.recyclerView.adapter = deviceListAdapter
} else {
deviceListAdapter?.setList(peerList.toList())
deviceListAdapter?.notifyDataSetChanged()
}
if(connectDevice==null) {
currentDirectState = DIRECT_REQUEST_PEER_UNFOUND
}
} else {
Log.i("tag", "未找到设备")
currentDirectState = DIRECT_REQUEST_PEER_UNFOUND
}
} else {
Log.i("tag", "未找到设备")
currentDirectState = DIRECT_REQUEST_PEER_UNFOUND
}
}
}
7.连接设备
/**
* 连接群组 、连接设备一样
*/
private fun connect(device: WifiP2pDevice) {
if (ActivityCompat.checkSelfPermission(
this@DirectWifiActivity,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ActivityCompat.checkSelfPermission(
this@DirectWifiActivity,
android.Manifest.permission.NEARBY_WIFI_DEVICES
) != PackageManager.PERMISSION_GRANTED
) {
return
}
}
/**
* WifiP2pDevice.AVAILABLE:可连接
* WifiP2pDevice.CONNECTED:已连接
* WifiP2pDevice.INVITED:已请求连接
*/
when (device.status) {
WifiP2pDevice.AVAILABLE -> {
// 请求连接
Log.i("tag", "发起连接 $device")
val config = WifiP2pConfig()
config.deviceAddress = device.deviceAddress
currentDirectState = DIRECT_REQUEST_CONNECT
wifiP2pManager!!.connect(channel,
config,
object : WifiP2pManager.ActionListener {
override fun onSuccess() {
// Connection initiated
currentDirectState = DIRECT_REQUEST_CONNECT_SUCCESS
Toast.makeText(
this@DirectWifiActivity,
"发起成功",
Toast.LENGTH_SHORT
).show()
Log.i("tag", "发起成功")
}
override fun onFailure(reason: Int) {
// Connection failed
currentDirectState = DIRECT_REQUEST_CONNECT_FAIL
Toast.makeText(
this@DirectWifiActivity,
"发起失败",
Toast.LENGTH_SHORT
).show()
Log.i("tag", "发起失败")
}
})
}
WifiP2pDevice.CONNECTED -> {
// 断开连接
// wifiP2pManager!!.removeGroup(channel, object : WifiP2pManager.ActionListener {
// override fun onSuccess() {
// Log.i("tag", "断开成功")
// }
//
// override fun onFailure(p0: Int) {
// Log.i("tag", "断开失败")
// }
//
// })
Log.i("tag", "已经连接")
requestConnectionInfo()
}
WifiP2pDevice.INVITED -> {
// 接受连接
// 关闭连接请求
wifiP2pManager!!.cancelConnect(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Log.i("TAG", "cancelConnect success.");
}
override fun onFailure(p0: Int) {
Log.i("TAG", "cancelConnect failed.");
}
})
}
}
}
8.断开连接
private fun cancelConnect() {
wifiP2pManager!!.cancelConnect(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Log.d("tag", "cancel success")
}
override fun onFailure(p0: Int) {
Log.d("tag", "cancel fail")
}
})
}
9.连接上后,可通过WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION广播去请求连接信息,作为客户端可以获取到服务端返回的信息,也可以作为服务端创建server
private fun requestConnectionInfo() {
currentDirectState = DIRECT_REQUEST_INFO
wifiP2pManager!!.requestConnectionInfo(
channel,
connectionInfoListener
)
}
private val connectionInfoListener =
WifiP2pManager.ConnectionInfoListener { info ->
if (info != null) {
currentDirectState = DIRECT_REQUEST_INFO_SUCCESS
if (info.groupFormed && info.isGroupOwner) {
// 服务端不需要做额外处理
Log.d("Client", "本设备为服务端");
startServer()
} else if (info.groupFormed) {
Log.d("Client", "本设备为客户端")
Log.d("Client", "服务端ip = ${info.groupOwnerAddress.hostAddress}")
createClientSocket(info.groupOwnerAddress.hostAddress)
}
} else {
currentDirectState = DIRECT_REQUEST_INFO_FAIL
Log.d("tag", "connectionInfo 为空");
}
}
10.还可以创建组群,移除组群,获取组群信息
wifiP2pManager!!.createGroup(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Toast.makeText(this@DirectWifiActivity, "Group created", Toast.LENGTH_SHORT).show()
}
override fun onFailure(reason: Int) {
Toast.makeText(
this@DirectWifiActivity,
"Failed to create group",
Toast.LENGTH_SHORT
)
.show()
}
})
wifiP2pManager!!.removeGroup(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Log.i("TAG", "onSuccess: removeGroup")
}
override fun onFailure(i: Int) {
Log.i("TAG", "onFailure: removeGroup")
}
})
wifiP2pManager!!.requestGroupInfo(channel) { wifiP2pGroup ->
if (wifiP2pGroup != null) {
Log.i("tag", "onGroupInfoAvailable: wifiP2pGroup != null")
} else {
Log.i("tag", "onGroupInfoAvailable: wifiP2pGroup == null")
}
}
11.案例
import android.Manifest
import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.net.wifi.WifiManager
import android.net.wifi.p2p.WifiP2pConfig
import android.net.wifi.p2p.WifiP2pDevice
import android.net.wifi.p2p.WifiP2pDeviceList
import android.net.wifi.p2p.WifiP2pManager
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.text.TextUtils
import android.util.Log
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.common.base.BaseActivity
import com.common.viewmodel.EmptyViewModel
import com.fei.firstproject.databinding.ActivityDirectWifiBinding
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.IOException
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.net.InetSocketAddress
import java.net.ServerSocket
import java.net.Socket
import kotlin.random.Random
/***
*
* 点对点wifi
* 以下 API 还需要启用位置信息模式:
*
* discoverPeers()
* discoverServices()
* requestPeers()
*
*/
class DirectWifiActivity : BaseActivity<EmptyViewModel, ActivityDirectWifiBinding>() {
private val PERMISSION_REQUEST_CODE = 1
private val wifiManager: WifiManager? by lazy(LazyThreadSafetyMode.NONE) {
applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
}
private val wifiP2pManager: WifiP2pManager? by lazy(LazyThreadSafetyMode.NONE) {
getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager?
}
private var currentDirectState = -1
private var channel: WifiP2pManager.Channel? = null
private var wifiP2pReceiver: BroadcastReceiver? = null
private var intentFilter: IntentFilter? = null
private var connectDevice: WifiP2pDevice? = null
private var deviceListAdapter: DeviceListAdapter? = null
private val DIRECT_DISCOVER_CONNECT = 1 //发现连接
private val DIRECT_DISCOVER_SUCCESS = 2 //发现成功
private val DIRECT_DISCOVER_FAIL = 3 //发现失败
private val DIRECT_REQUEST_PEER = 4 //请求peer
private val DIRECT_REQUEST_PEER_FOUND = 5 //找到
private val DIRECT_REQUEST_PEER_UNFOUND = 6 //找不到
private val DIRECT_REQUEST_CONNECT = 7//发起连接
private val DIRECT_REQUEST_CONNECT_SUCCESS = 8//还请连接成功
private val DIRECT_REQUEST_CONNECT_FAIL = 9//发起连接失败
private val DIRECT_REQUEST_INFO = 10 //发起获取设备信息
private val DIRECT_REQUEST_INFO_SUCCESS = 11 //获取设备信息成功
private val DIRECT_REQUEST_INFO_FAIL = 12 //获取设备信息失败
override fun createObserver() {
}
override fun initViewAndData(savedInstanceState: Bundle?) {
mBinding.btnCreateGroup.setOnClickListener {
createGroup()
}
mBinding.btnConnectGroup.setOnClickListener {
connectDevice?.let { connectGroup(it) }
}
mBinding.btnRemoveGroup.setOnClickListener {
removeGroup()
}
mBinding.btnDiscover.setOnClickListener {
discoverPeers()
}
mBinding.btnConnect.setOnClickListener {
connectDevice?.let { connect(it) }
}
mBinding.btnSend.setOnClickListener {
sendMessage()
}
mBinding.btnCancel.setOnClickListener {
cancelConnect()
}
mBinding.btnRequestGroupInfo.setOnClickListener {
requestGroupInfo()
}
mBinding.btnConnectInfo.setOnClickListener {
requestConnectionInfo()
}
if (initP2p()) {
receiveReigst()
}
}
private fun receiveReigst() {
intentFilter = 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)
wifiP2pReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION == action) {
Log.i("tag", "当在设备上启用或停用 Wi-Fi 点对点时广播。")
val state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1)
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
// WiFi P2P is enabled
Log.i("tag", "状态改变 WiFi P2P is enabled")
//todo
//可搜索周围P2P设备 discoverPeers
} else {
// WiFi P2P is not enabled
Log.i("tag", "状态改变 WiFi P2P is not enabled");
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION == action) {
Log.i(
"tag",
"当您调用 discoverPeers() 时广播。如果您在应用中处理此 intent,则通常需要调用 requestPeers() 来获取更新后的对等设备列表。"
);
// Request available peers from the WifiP2pManager
if (currentDirectState != DIRECT_DISCOVER_SUCCESS) {
return
}
currentDirectState = DIRECT_REQUEST_PEER
requestPeers()
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION == action) {
Log.i(
"tag",
"表明Wi-Fi对等网络的连接状态发生了改变,应用可以使用 requestConnectionInfo()、requestNetworkInfo() 或 requestGroupInfo() 来检索当前连接信息。 "
);
// Respond to new connection or disconnections
if (currentDirectState != DIRECT_REQUEST_CONNECT_SUCCESS) {
Log.i("tag", "当前状态不需要请求连接信息")
return
}
requestConnectionInfo()
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION == action) {
Log.i("tag", "表明该设备的配置信息发生了改变");
val device: WifiP2pDevice? =
intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE)
Log.i(
"tag",
"本设备信息发生变化:" + device!!.deviceName + ", " + device.deviceAddress
)
requestDeviceInfo()
// Respond to this device's wifi state changing
}
}
}
registerReceiver(wifiP2pReceiver, intentFilter)
}
private fun requestDeviceInfo() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
this,
Manifest.permission.NEARBY_WIFI_DEVICES
) != PackageManager.PERMISSION_GRANTED
) {
return
}
wifiP2pManager!!.requestDeviceInfo(channel!!
) { p0 -> Log.i("tag", p0!!.toString()) }
}
}
private fun requestPeers() {
if (ActivityCompat.checkSelfPermission(
this@DirectWifiActivity,
android.Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this@DirectWifiActivity,
arrayOf<String>(android.Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSION_REQUEST_CODE
)
return
}
wifiP2pManager!!.requestPeers(channel, peerListListener)
}
private fun requestConnectionInfo() {
currentDirectState = DIRECT_REQUEST_INFO
wifiP2pManager!!.requestConnectionInfo(
channel,
connectionInfoListener
)
}
private fun connectGroup(
wifiP2pDevice: WifiP2pDevice
) {
// 如果连接对象为群组GroupOwner
if (wifiP2pDevice.isGroupOwner) {
connect(wifiP2pDevice)
} else {
Log.i("TAG", "对方设备不是群组")
}
}
private fun requestGroupInfo() {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ActivityCompat.checkSelfPermission(
this@DirectWifiActivity,
android.Manifest.permission.NEARBY_WIFI_DEVICES
) != PackageManager.PERMISSION_GRANTED
) {
return
}
}
wifiP2pManager!!.requestGroupInfo(channel) { wifiP2pGroup ->
if (wifiP2pGroup != null) {
Log.i("tag", "onGroupInfoAvailable: wifiP2pGroup != null")
} else {
Log.i("tag", "onGroupInfoAvailable: wifiP2pGroup == null")
}
}
}
private fun removeGroup() {
wifiP2pManager!!.removeGroup(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Log.i("TAG", "onSuccess: removeGroup")
}
override fun onFailure(i: Int) {
Log.i("TAG", "onFailure: removeGroup")
}
})
}
private fun cancelConnect() {
wifiP2pManager!!.cancelConnect(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Log.d("tag", "cancel success")
}
override fun onFailure(p0: Int) {
Log.d("tag", "cancel fail")
}
})
}
private var serverSocket: ServerSocket? = null
private fun startServer() {
// 创建服务器 Socket
if (serverSocket != null) {
return
}
try {
serverSocket = ServerSocket(8888)
Toast.makeText(this@DirectWifiActivity, "服务器 Socket 已创建", Toast.LENGTH_LONG)
.show()
} catch (e: IOException) {
e.printStackTrace()
}
// 开启接收线程监听客户端连接
val acceptThread = Thread {
try {
// 等待客户端连接
val socket: Socket = serverSocket!!.accept()
Toast.makeText(this@DirectWifiActivity, "客户端已连接", Toast.LENGTH_LONG).show()
while (true) {
// 读取客户端发送的数据
val reader = BufferedReader(InputStreamReader(socket.getInputStream()))
val data = reader.readLine()
runOnUiThread {
Toast.makeText(this@DirectWifiActivity, "收到数据$data", Toast.LENGTH_LONG)
.show()
}
// 发送响应给客户端
val writer =
BufferedWriter(OutputStreamWriter(socket.getOutputStream()))
writer.write(Random.nextInt(1000).toString())
writer.newLine()
writer.flush()
}
} catch (e: IOException) {
e.printStackTrace()
}
}
acceptThread.start()
}
private var clientSocket: Socket? = null
private fun sendMessage() {
if (clientSocket == null && connectDevice != null) {
createClientSocket(connectDevice!!.deviceAddress)
}
if (clientSocket == null) {
return
}
val thread = Thread {
try {
// 向服务端发送数据
val writer = BufferedWriter(OutputStreamWriter(clientSocket!!.getOutputStream()))
writer.write(Random.nextInt(1000).toString())
writer.newLine()
writer.flush()
// 读取服务端响应数据
val reader = BufferedReader(InputStreamReader(clientSocket!!.getInputStream()))
val data = reader.readLine()
runOnUiThread {
Toast.makeText(this@DirectWifiActivity, "收到数据$data", Toast.LENGTH_LONG)
.show()
}
Log.d("Client", "服务端返回的响应:$data")
} catch (e: IOException) {
e.printStackTrace()
clientSocket!!.close()
clientSocket = null
}
}
thread.start()
}
/**
* 连接群组 、连接设备一样
*/
private fun connect(device: WifiP2pDevice) {
if (ActivityCompat.checkSelfPermission(
this@DirectWifiActivity,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ActivityCompat.checkSelfPermission(
this@DirectWifiActivity,
android.Manifest.permission.NEARBY_WIFI_DEVICES
) != PackageManager.PERMISSION_GRANTED
) {
return
}
}
/**
* WifiP2pDevice.AVAILABLE:可连接
* WifiP2pDevice.CONNECTED:已连接
* WifiP2pDevice.INVITED:已请求连接
*/
when (device.status) {
WifiP2pDevice.AVAILABLE -> {
// 请求连接
Log.i("tag", "发起连接 $device")
val config = WifiP2pConfig()
config.deviceAddress = device.deviceAddress
currentDirectState = DIRECT_REQUEST_CONNECT
wifiP2pManager!!.connect(channel,
config,
object : WifiP2pManager.ActionListener {
override fun onSuccess() {
// Connection initiated
currentDirectState = DIRECT_REQUEST_CONNECT_SUCCESS
Toast.makeText(
this@DirectWifiActivity,
"发起成功",
Toast.LENGTH_SHORT
).show()
Log.i("tag", "发起成功")
}
override fun onFailure(reason: Int) {
// Connection failed
currentDirectState = DIRECT_REQUEST_CONNECT_FAIL
Toast.makeText(
this@DirectWifiActivity,
"发起失败",
Toast.LENGTH_SHORT
).show()
Log.i("tag", "发起失败")
}
})
}
WifiP2pDevice.CONNECTED -> {
// 断开连接
// wifiP2pManager!!.removeGroup(channel, object : WifiP2pManager.ActionListener {
// override fun onSuccess() {
// Log.i("tag", "断开成功")
// }
//
// override fun onFailure(p0: Int) {
// Log.i("tag", "断开失败")
// }
//
// })
Log.i("tag", "已经连接")
requestConnectionInfo()
}
WifiP2pDevice.INVITED -> {
// 接受连接
// 关闭连接请求
wifiP2pManager!!.cancelConnect(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Log.i("TAG", "cancelConnect success.");
}
override fun onFailure(p0: Int) {
Log.i("TAG", "cancelConnect failed.");
}
})
}
}
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
private fun createGroup() {
if (serverSocket != null) {
return
}
// Check if location permission is granted
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSION_REQUEST_CODE
)
return
}
// Check if location service is enabled
if (!wifiManager!!.isWifiEnabled) {
Toast.makeText(this, "Please enable WiFi", Toast.LENGTH_SHORT).show()
startActivity(Intent(Settings.ACTION_WIFI_SETTINGS))
return
}
wifiP2pManager!!.createGroup(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Toast.makeText(this@DirectWifiActivity, "Group created", Toast.LENGTH_SHORT).show()
}
override fun onFailure(reason: Int) {
Toast.makeText(
this@DirectWifiActivity,
"Failed to create group",
Toast.LENGTH_SHORT
)
.show()
}
})
}
/**
* 初始化
*/
private fun initP2p(): Boolean {
// Device capability definition check
if (!packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)) {
Log.e("TAG", "Wi-Fi Direct is not supported by this device.")
return false
}
// Hardware capability check
if (wifiManager == null) {
Log.e("TAG", "Cannot get Wi-Fi system service.")
return false
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (!wifiManager!!.isP2pSupported) {
Log.e("TAG", "Wi-Fi Direct is not supported by the hardware or Wi-Fi is off.")
return false
}
}
if (wifiP2pManager == null) {
Log.e("TAG", "Cannot get Wi-Fi Direct system service.")
return false
}
channel = wifiP2pManager!!.initialize(this@DirectWifiActivity, mainLooper, null)
if (channel == null) {
Log.e("TAG", "Cannot initialize Wi-Fi Direct.")
return false
}
return true
}
private fun isLocationEnabled(): Boolean {
val locationMode: Int
val locationProviders: String
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
locationMode = Settings.Secure.getInt(
contentResolver,
Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_OFF
)
locationMode != Settings.Secure.LOCATION_MODE_OFF
} else {
locationProviders = Settings.Secure.getString(
contentResolver,
Settings.Secure.LOCATION_PROVIDERS_ALLOWED
)
!TextUtils.isEmpty(locationProviders)
}
}
private fun discoverPeers() {
// Check if location permission is granted
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION
),
PERMISSION_REQUEST_CODE
)
return
}
// Check if location service is enabled
if (!wifiManager!!.isWifiEnabled) {
Toast.makeText(this@DirectWifiActivity, "Please enable WiFi", Toast.LENGTH_SHORT).show()
val panelIntent = Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY)
val componentName = panelIntent.resolveActivity(packageManager)
if (componentName != null) {
startActivity(panelIntent)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startActivity(Intent(Settings.ACTION_WIFI_SETTINGS))
} else {
wifiManager!!.setWifiEnabled(true)//android Q 默认返回false
}
return
}
if (!isLocationEnabled()) {
Toast.makeText(this@DirectWifiActivity, "Please enable Location", Toast.LENGTH_SHORT)
.show()
startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS))
return
}
currentDirectState = DIRECT_DISCOVER_CONNECT
wifiP2pManager!!.discoverPeers(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
// Peers discovery initiated
currentDirectState = DIRECT_DISCOVER_SUCCESS
Toast.makeText(this@DirectWifiActivity, "Discovering peers", Toast.LENGTH_SHORT)
.show()
}
override fun onFailure(reason: Int) {
currentDirectState = DIRECT_DISCOVER_FAIL
Toast.makeText(
this@DirectWifiActivity,
"Failed to discover peers $reason",
Toast.LENGTH_SHORT
)
.show()
}
})
}
private val connectionInfoListener =
WifiP2pManager.ConnectionInfoListener { info ->
if (info != null) {
currentDirectState = DIRECT_REQUEST_INFO_SUCCESS
if (info.groupFormed && info.isGroupOwner) {
// 服务端不需要做额外处理
Log.d("Client", "本设备为服务端");
startServer()
} else if (info.groupFormed) {
Log.d("Client", "本设备为客户端")
Log.d("Client", "服务端ip = ${info.groupOwnerAddress.hostAddress}")
createClientSocket(info.groupOwnerAddress.hostAddress)
}
} else {
currentDirectState = DIRECT_REQUEST_INFO_FAIL
Log.d("tag", "connectionInfo 为空");
}
}
private fun createClientSocket(address: String) {
val thread = Thread {
if (clientSocket == null) {
try {
clientSocket = Socket()
val inetSocketAddress = InetSocketAddress(address, 8888)
clientSocket!!.bind(null)
clientSocket!!.connect(inetSocketAddress, 5000)
Log.d("Client", "连接服务器成功:" + clientSocket!!.inetAddress)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
thread.start()
}
private fun stopPeerDiscovery() {
Log.i("tag", "停止找寻设备")
wifiP2pManager!!.stopPeerDiscovery(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Log.i("tag", "停止成功")
}
override fun onFailure(p0: Int) {
Log.i("tag", "停止成功")
}
})
}
/**
*/
private fun disconnectP2pWifi() {
wifiP2pManager!!.removeGroup(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Log.i("tag", "断开成功")
}
override fun onFailure(p0: Int) {
Log.i("tag", "断开失败")
}
})
}
/**
* discover 收到的设备信息
*/
private val peerListListener = object : WifiP2pManager.PeerListListener {
@SuppressLint("NotifyDataSetChanged")
override fun onPeersAvailable(peers: WifiP2pDeviceList?) {
if (peers != null) {
val peerList = peers.deviceList
Log.i("tag", peerList.toString())
if (peerList.isNotEmpty()) {
if (deviceListAdapter == null) {
deviceListAdapter =
DeviceListAdapter(this@DirectWifiActivity, peerList.toList())
mBinding.recyclerView.layoutManager = LinearLayoutManager(
this@DirectWifiActivity,
LinearLayoutManager.VERTICAL,
false
)
mBinding.recyclerView.adapter = deviceListAdapter
} else {
deviceListAdapter?.setList(peerList.toList())
deviceListAdapter?.notifyDataSetChanged()
}
peerList.forEach {
if (it.deviceName == "Android_79b2") {
connectDevice = it
currentDirectState = DIRECT_REQUEST_PEER_FOUND
Log.i("tag", "找到设备了")
} else if (it.status == WifiP2pDevice.CONNECTED) {
//断开其他设备,才能连接该设备
Log.i("tag", "断开${it.deviceName}")
disconnectP2pWifi()
return@forEach
}
}
if(connectDevice==null) {
currentDirectState = DIRECT_REQUEST_PEER_UNFOUND
}
} else {
Log.i("tag", "未找到设备")
currentDirectState = DIRECT_REQUEST_PEER_UNFOUND
}
} else {
Log.i("tag", "未找到设备")
currentDirectState = DIRECT_REQUEST_PEER_UNFOUND
}
}
}
override fun onDestroy() {
super.onDestroy()
if (wifiP2pReceiver != null) {
unregisterReceiver(wifiP2pReceiver)
}
if (clientSocket != null) {
clientSocket!!.close()
}
if (serverSocket != null) {
serverSocket!!.close()
}
}
}
文章上如有错误,欢迎留言,谢谢大家支持