成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

走進Android WiFi P2P技術,一探設備間點對點通信實現細節

移動開發 Android
WiFi P2P被廣泛應用于移動設備之間的文件共享、游戲聯機、音樂播放等應用場景中。相較于藍牙,WiFi P2P具有更快的搜索速度和傳輸速度,以及更遠的傳輸距離。而且只需要打開WiFi即可,不需要加入任何網絡或AP,即可實現對等點連接通訊。對于需要在用戶之間共享數據的應用,如多人游戲或照片共享非常有用。

WiFi P2P技術

WiFi P2P(Peer-to-Peer),也被稱為WiFi Direct,是WiFi聯盟發布的一個協議。允許無線網絡中的設備在無需無線路由器的情況下相互連接,通過WiFi直接實現兩臺設備之間的無線點對點通信。原理與基于AP(接入點)的通信方式類似,支持P2P的設備可以在同一個小組內互傳數據,實現同屏功能。

WiFi P2P被廣泛應用于移動設備之間的文件共享、游戲聯機、音樂播放等應用場景中。相較于藍牙,WiFi P2P具有更快的搜索速度和傳輸速度,以及更遠的傳輸距離。而且只需要打開WiFi即可,不需要加入任何網絡或AP,即可實現對等點連接通訊。對于需要在用戶之間共享數據的應用,如多人游戲或照片共享非常有用。

WiFi P2P也存在一些安全性問題,如用戶隱私泄露、惡意軟件和病毒傳播,以及侵權和違法內容的傳播。為了保護用戶的安全和隱私,一些P2P網絡提供了匿名化處理功能,使用安全搜索引擎,以及設置過濾器來阻止違法和侵權內容的共享。

Android WiFi P2P架構

在P2P架構中,定義了兩種主要角色:P2P Group Owner(簡稱GO)和P2P Client(簡稱GC)。GO的作用類似于Infrastructure BSS中的AP(接入點),而GC的作用類似于Infrastructure BSS中的STA(站點)。當兩臺設備通過P2P連接后,會隨機(也可以手動指定)指派其中一臺設備為組擁有者(GO),相當于一臺服務器,另一臺設備為組成員(GC)。其他設備可以通過與GO設備連接加入組,但不能直接和GC設備連接。

圖片圖片

在Android系統中,WiFi P2P功能是在Android 4.0及更高版本系統中加入的。它可以通過WifiP2pManager類進行實現,這個類提供了許多方法來掃描可用設備、建立P2P連接并傳輸數據等功能。開發者可以通過這些方法來實現設備之間的文件傳輸等操作。

在設備發現階段,Android WiFi P2P使用Probe Request和Probe Response幀來交換設備信息。在2.4GHz的1、6、11頻段上發送Probe Request幀,這幾個頻段被稱為Social Channels。一旦Listen Channel選擇好后,在整個P2P Discovery階段就不能更改,用于快速發現周圍的Group。

盡管Android WiFi P2P功能強大,目前在Android系統中只是內置了設備的搜索和鏈接功能,并沒有像藍牙那樣有許多應用。在實際開發中,可能需要通過軟件手段解決一些邏輯和權限問題。

Android應用WiFi P2P實現數據傳輸

在Android中,WiFi P2P可以通過WifiP2pManager類進行實現。開發者可以通過獲取WifiP2pManager實例,并進行廣播接受者的創建和注冊,調用其他WiFi P2P的API,實現設備間的搜索、連接和數據傳輸等功能。例如,指定某一臺設備為服務器,創建群組并等待客戶端的連接請求,而客戶端則可以主動搜索附近的設備并加入群組,向服務器發起文件傳輸請求。

圖片圖片

添加權限
<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_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
獲取WifiP2pManager和WifiP2pManager.Channel對象
mWifiP2pManager = getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager
mWifiP2pManager?.initialize(this, Looper.getMainLooper()) {
    Log.d(TAG, "Channel斷開連接")
}
服務端創建群組
//服務端創建群組
mWifiP2pManager?.createGroup(mChannel, object : WifiP2pManager.ActionListener {
    override fun onSuccess() {
        Log.d(TAG, "創建群組成功")
    }

    override fun onFailure(reason: Int) {
        Log.w(TAG, "創建群組失敗$reason")
    }
})
客戶端搜索對等設備
//客戶端搜索對等設備
mWifiP2pManager?.discoverPeers(mChannel, object : WifiP2pManager.ActionListener {
    override fun onSuccess() {
        Log.d(TAG, "搜索成功")
    }

    override fun onFailure(reason: Int) {
        Log.d(TAG, "搜索失敗:$reason")
    }

})
//使用異步方法(推薦通過廣播監聽) 獲取設備列表
mWifiP2pManager?.requestPeers(mChannel) {
    mDeviceList.addAll(it.deviceList)
    if (mDeviceList.isEmpty()) {
        //沒有設備
        runOnUiThread { Toast.makeText(this, "沒有發現設備", Toast.LENGTH_SHORT).show() }
    } else {
        //刷新列表
        runOnUiThread { mDeviceAdapter.notifyDataSetChanged() }
    }
}
連接設備
val config = WifiP2pConfig().apply {
    this.deviceAddress = wifiP2pDevice.deviceAddress
    this.wps.setup = WpsInfo.PBC
}
mWifiP2pManager?.connect(mChannel, config, object : WifiP2pManager.ActionListener {
    override fun onSuccess() {
        Log.d(TAG, "連接成功")
    }

    override fun onFailure(reason: Int) {
        Log.w(TAG, "連接失敗$reason")
    }

})
服務端創建Socket進行數據讀寫
// 將數據發送給客戶端
//需要創建子線程 否則在主線程網絡操作直接閃退
val serverSocket = ServerSocket(8888)
val socket = serverSocket.accept()
val inputStream = socket.getInputStream()
val outputStream = socket.getOutputStream()
//發送數據
outputStream?.write(data)
//此處為了方便 實際需要開啟線程讀取 并且要有合適的延遲
while (!mQuitReadData) {
    val reader = inputStream.bufferedReader(StandardCharsets.UTF_8)
    val text = reader.readLine()
    Log.d(TAG, "讀取到的數據$text")
}
客戶端創建Socket進行數據讀寫
//需要創建子線程 否則在主線程網絡操作直接閃退
val address: InetAddress = info.groupOwnerAddress
val socket = Socket(address, 8888)
val inputStream = socket.getInputStream()
val outputStream = socket.getOutputStream()
//發送數據
outputStream?.write(data)
//此處為了方便 實際需要開啟線程讀取 并且要有合適的延遲
while (!mQuitReadData) {
    val reader = inputStream.bufferedReader(StandardCharsets.UTF_8)
    val text = reader.readLine()
    Log.d(TAG, "讀取到的數據$text")
}
class MainActivity : AppCompatActivity() {

    private val TAG = MainActivity::class.java.simpleName

    private lateinit var mBinding: ActivityMainBinding

    private var mWifiP2pManager: WifiP2pManager? = null
    private var mChannel: WifiP2pManager.Channel? = null

    private var mDeviceList = arrayListOf<WifiP2pDevice>()
    private lateinit var mDeviceAdapter: DeviceAdapter

    private var mQuitReadData = true

    @SuppressLint("NotifyDataSetChanged")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        mBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(mBinding.root)
        ViewCompat.setOnApplyWindowInsetsListener(mBinding.main) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        val 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)
        registerReceiver(mReceiver, intentFilter)

        mDeviceAdapter = DeviceAdapter(mDeviceList)
        mBinding.rvDeviceList.adapter = mDeviceAdapter
        mDeviceAdapter.mOnItemSelectedListener = object : OnItemSelectedListener {
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                val wifiP2pDevice = mDeviceList[position]
                connect(wifiP2pDevice)
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {
            }
        }

        //通用步驟
        mWifiP2pManager = getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager

        mChannel = mWifiP2pManager?.initialize(this, Looper.getMainLooper()) {
            Log.d(TAG, "Channel斷開連接")
        }

        //服務端部分
        //服務端創建群組
        mWifiP2pManager?.createGroup(mChannel, object : WifiP2pManager.ActionListener {
            override fun onSuccess() {
                Log.d(TAG, "創建群組成功")
            }

            override fun onFailure(reason: Int) {
                Log.w(TAG, "創建群組失敗$reason")
            }
        })

        //客戶端部分
        //客戶端搜索對等設備
        mWifiP2pManager?.discoverPeers(mChannel, object : WifiP2pManager.ActionListener {
            override fun onSuccess() {
                Log.d(TAG, "搜索成功")
            }

            override fun onFailure(reason: Int) {
                Log.d(TAG, "搜索失敗:$reason")
            }

        })

        //使用異步方法(推薦通過廣播監聽) 獲取設備列表
        mWifiP2pManager?.requestPeers(mChannel) {
            mDeviceList.addAll(it.deviceList)
            if (mDeviceList.isEmpty()) {
                //沒有設備
                runOnUiThread { Toast.makeText(this, "沒有發現設備", Toast.LENGTH_SHORT).show() }
            } else {
                //刷新列表
                runOnUiThread { mDeviceAdapter.notifyDataSetChanged() }
            }
        }
    }

    /**
     * 連接設備
     */
    private fun connect(wifiP2pDevice: WifiP2pDevice) {
        val config = WifiP2pConfig().apply {
            this.deviceAddress = wifiP2pDevice.deviceAddress
            this.wps.setup = WpsInfo.PBC
        }
        mWifiP2pManager?.connect(mChannel, config, object : WifiP2pManager.ActionListener {
            override fun onSuccess() {
                Log.d(TAG, "連接成功")
                mQuitReadData = false
                transferData("Hello".toByteArray())
            }

            override fun onFailure(reason: Int) {
                Log.w(TAG, "連接失敗$reason")
                mQuitReadData = true
            }

        })
    }

    private fun transferData(data: ByteArray) {
        //請求設備連接信息
        mWifiP2pManager?.requestConnectionInfo(mChannel) { info ->
            if (info.groupFormed && info.isGroupOwner) {
                // 將數據發送給客戶端
                val serverSocket = ServerSocket(8888)
                val socket = serverSocket.accept()
                val inputStream = socket.getInputStream()
                val outputStream = socket.getOutputStream()
                //發送數據
                outputStream?.write(data)
                //此處為了方便 實際需要開啟線程讀取 并且要有合適的延遲
                while (!mQuitReadData) {
                    val reader = inputStream.bufferedReader(StandardCharsets.UTF_8)
                    val text = reader.readLine()
                    Log.d(TAG, "讀取到的數據$text")
                }
            } else {
                //設備是客戶端
                val address: InetAddress = info.groupOwnerAddress
                val socket = Socket(address, 8888)
                val inputStream = socket.getInputStream()
                val outputStream = socket.getOutputStream()
                //發送數據
                outputStream?.write(data)
                //此處為了方便 實際需要開啟線程讀取 并且要有合適的延遲
                while (!mQuitReadData) {
                    val reader = inputStream.bufferedReader(StandardCharsets.UTF_8)
                    val text = reader.readLine()
                    Log.d(TAG, "讀取到的數據$text")
                }
            }
        }
    }

    private val mReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val action = intent?.action;
            if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
                // Check to see if Wi-Fi is enabled and notify appropriate activity
                // 檢查 Wi-Fi P2P 是否已啟用
                val state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1)
                val isEnabled = (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED)
            } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
                // Call WifiP2pManager.requestPeers() to get a list of current peers
                //異步方法
                // mWifiP2pManager?.requestPeers();
            } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
                // Respond to new connection or disconnections
                // 鏈接狀態變化回調
                // 此廣播 會和 WIFI_P2P_THIS_DEVICE_CHANGED_ACTION 同時回調
                // 注冊廣播、連接成功、連接失敗 三種時機都會調用
                // 應用可使用 requestConnectionInfo()、requestNetworkInfo() 或 requestGroupInfo() 來檢索當前連接信息。
            } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
                // Respond to this device's wifi state changing
                // 此設備的WiFi狀態更改回調
                // 此廣播 會和 WIFI_P2P_CONNECTION_CHANGED_ACTION 同時回調
                // 注冊廣播、連接成功、連接失敗 三種時機都會調用
                // 應用可使用 requestDeviceInfo() 來檢索當前連接信息。
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        //移除群組
        mWifiP2pManager?.removeGroup(mChannel, null)
        //取消鏈接
        mWifiP2pManager?.cancelConnect(mChannel, null)
    }
}

Android WiFi P2P使用流程總結:

  1. 「權限聲明」:

在AndroidManifest.xml中聲明必要的權限,包括網絡訪問權限和文件讀寫權限。

  1. 「初始化」:

在Android應用中,首先需要獲取WifiP2pManager實例,并通過調用其initialize方法進行初始化。這將注冊應用并準備使用Wi-Fi P2P功能。

初始化完成后,會獲得一個Channel對象,它是后續操作的關鍵。

3.「廣播接收與處理」:

在整個過程中,應用需要注冊并監聽特定的廣播,以處理Wi-Fi P2P狀態變化、設備發現、連接變化等事件。

這些廣播會通知應用有關Wi-Fi P2P操作的狀態和結果,以便應用可以做出相應的響應。

4.「設備發現」:

使用WifiP2pManager的discoverPeers方法開始搜索附近的Wi-Fi P2P設備。

設備會在特定的頻段(如2.4GHz的1、6、11頻段)上發送Probe Request幀來尋找其他設備。

搜索到的設備會作為列表展示在應用界面上,用戶可以從中選擇想要連接的設備。

5.「建立連接」:

選定一個設備后,作為客戶端或服務端(Group Owner,GO)發起連接請求。

通過WifiP2pConfig對象配置連接參數,如目標設備的地址和WPS(Wi-Fi Protected Setup)設置。

使用WifiP2pManager的connect方法嘗試建立連接。

6.「連接確認與數據傳輸」:

一旦連接建立成功,設備之間就可以開始數據傳輸了。

可以通過Socket編程在設備之間建立連接,并傳輸文件或其他數據。

根據應用需求,可以創建服務端套接字監聽客戶端的連接請求,也可以作為客戶端主動連接到服務端。

7.「數據傳輸完成與斷開連接」:

數據傳輸完成后,應用需要適當地關閉套接字和斷開Wi-Fi P2P連接。

使用WifiP2pManager的相關方法來斷開連接,并釋放相關資源。

責任編輯:武曉燕 來源: 沐雨花飛蝶
相關推薦

2024-08-06 14:03:35

2012-12-10 09:46:21

P2P云存儲Symform

2009-04-07 10:39:13

2009-05-18 09:11:00

IPTV融合寬帶

2010-07-13 14:41:14

2010-03-22 15:27:40

云計算

2020-03-05 20:30:15

Syncthing文件同步工具開源

2011-11-17 16:58:11

AndroidAdobeAIR

2022-07-19 16:59:04

流媒體傳輸IPC物聯網

2023-03-14 12:43:57

2011-12-19 09:46:31

2010-10-29 09:43:50

Wi-Fi DirecWi-Fi聯

2017-11-20 17:53:00

阿里開源容器

2018-08-16 07:29:02

2015-04-27 11:49:23

2012-09-25 13:47:43

C#網絡協議P2P

2010-06-28 11:15:45

BitTorrent協

2010-03-10 10:51:30

2010-07-07 10:31:45

2013-03-13 09:24:56

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久久久无码av | 亚洲高清视频一区二区 | 中文一区二区视频 | 日韩免| 亚洲成人一区二区 | 香蕉视频一区二区 | 亚洲精品在线视频 | 久久国产精品偷 | 国产在线播放一区二区三区 | 一区二区三区国产精品 | 久久伦理中文字幕 | 一区二区三区小视频 | 日韩av第一页 | 欧美午夜一区 | 天天干亚洲 | www久久国产| 欧美福利 | 亚洲精品一区二区在线观看 | 久久国产精品网站 | 日本又色又爽又黄的大片 | 色就是色欧美 | 亚洲精品乱码久久久久久按摩观 | 成人午夜在线 | 成人一区二区三区在线观看 | 国产激情一区二区三区 | 亚洲精品欧美精品 | 成人久久视频 | 毛片a级毛片免费播放100 | 色橹橹欧美在线观看视频高清 | 日韩视频在线一区 | 欧美国产日韩精品 | 91视频大全| 亚洲综合色 | 人人人人干| 一级特黄a大片 | 日韩免费视频一区二区 | 欧美一级免费片 | 国产一区二区三区四区三区四 | 成人精品鲁一区一区二区 | 日韩www| 91国内视频在线 |