Bladeren bron

ble service

zhaoyadi 8 maanden geleden
bovenliggende
commit
269e6ba7ef
20 gewijzigde bestanden met toevoegingen van 345 en 255 verwijderingen
  1. 1 0
      .idea/codeStyles/Project.xml
  2. 68 148
      xiaodou/src/main/java/com/luojigou/xiaodou/XDScanBLEActivity.kt
  3. 0 55
      xiaodou/src/main/java/com/luojigou/xiaodou/XDScanBLEAdapter.kt
  4. 15 0
      xiaodou/src/main/java/com/luojigou/xiaodou/XDScanBLEService.kt
  5. 0 13
      xiaodou/src/main/java/com/luojigou/xiaodou/XDScanBLEStatus.kt
  6. 5 0
      xiaodou/src/main/java/com/luojigou/xiaodou/ble/BLEConnectStatus.kt
  7. 66 0
      xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEAdapter.kt
  8. 21 0
      xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEDevice.kt
  9. 6 5
      xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEDisableFragment.kt
  10. 70 6
      xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLENormalFragment.kt
  11. 13 0
      xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLENotSupportFragment.kt
  12. 11 10
      xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEPermissionFragment.kt
  13. 5 2
      xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEStatus.kt
  14. 5 5
      xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiAdapter.kt
  15. 0 1
      xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiNormalFragment.kt
  16. 4 1
      xiaodou/src/main/res/layout/fragment_scanble_normal.xml
  17. 1 1
      xiaodou/src/main/res/layout/fragment_scanble_permission.xml
  18. 1 1
      xiaodou/src/main/res/layout/fragment_scanwifi_permission.xml
  19. 34 6
      xiaodou/src/main/res/layout/item_ble.xml
  20. 19 1
      xiaodou/src/main/res/layout/item_wifi.xml

+ 1 - 0
.idea/codeStyles/Project.xml

@@ -10,6 +10,7 @@
       <option name="SPACE_BEFORE_COLON" value="false" />
     </codeStyleSettings>
     <codeStyleSettings language="JAVA">
+      <option name="RIGHT_MARGIN" value="140" />
       <option name="KEEP_LINE_BREAKS" value="false" />
       <option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
       <option name="KEEP_SIMPLE_BLOCKS_IN_ONE_LINE" value="true" />

+ 68 - 148
xiaodou/src/main/java/com/luojigou/xiaodou/XDScanBLEActivity.kt

@@ -1,32 +1,32 @@
 package com.luojigou.xiaodou
 
 import android.Manifest
-import android.annotation.SuppressLint
 import android.bluetooth.BluetoothAdapter
 import android.bluetooth.BluetoothManager
-import android.bluetooth.le.ScanCallback
-import android.bluetooth.le.ScanFilter
-import android.bluetooth.le.ScanResult
-import android.bluetooth.le.ScanSettings
 import android.content.BroadcastReceiver
+import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
+import android.content.ServiceConnection
 import android.content.pm.PackageManager
 import android.os.Build
 import android.os.Bundle
+import android.os.IBinder
 import android.util.Log
-import android.view.View
-import android.widget.Button
-import android.widget.ProgressBar
-import android.widget.TextView
-import androidx.activity.result.contract.ActivityResultContracts
 import androidx.appcompat.app.AppCompatActivity
+import androidx.bluetooth.BluetoothDevice
+import androidx.bluetooth.BluetoothLe
 import androidx.core.app.ActivityCompat
-import androidx.recyclerview.widget.RecyclerView
+import androidx.fragment.app.Fragment
+import com.luojigou.xiaodou.ble.XDScanBLEDisableFragment
+import com.luojigou.xiaodou.ble.XDScanBLENormalFragment
+import com.luojigou.xiaodou.ble.XDScanBLENotSupportFragment
+import com.luojigou.xiaodou.ble.XDScanBLEPermissionFragment
+import com.luojigou.xiaodou.ble.XDScanBLEStatus
 
 
-class XDScanBLEActivity : AppCompatActivity() {
+class XDScanBLEActivity : AppCompatActivity(), XDScanBLEStatus.Host {
     private val permissions: Array<String> by lazy {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
             arrayOf(
@@ -41,10 +41,17 @@ class XDScanBLEActivity : AppCompatActivity() {
         }
     }
 
-    private lateinit var txtMsg: TextView
-    private lateinit var btnScan: Button
-    private lateinit var listview: RecyclerView
-    private lateinit var progress: ProgressBar
+    private val disableFragment = XDScanBLEDisableFragment(this)
+    private val normalFragment = XDScanBLENormalFragment(this)
+    private val permissionFragment = XDScanBLEPermissionFragment(this)
+    private val notsupportFragment = XDScanBLENotSupportFragment(this)
+
+
+    private val bluetoothManager: BluetoothManager by lazy {
+        getSystemService(BLUETOOTH_SERVICE) as BluetoothManager
+    }
+
+    private var bluetoothBinder: XDScanBLEService.XDScanBLEBinder? = null
 
     private val broadcastReceiver by lazy {
         object : BroadcastReceiver() {
@@ -58,12 +65,12 @@ class XDScanBLEActivity : AppCompatActivity() {
 
                 when (currentState) {
                     BluetoothAdapter.STATE_OFF -> { // 蓝牙已关闭
-                        maybeSetupBluetooth()
+                        checkBluetoothPermissionAndEnable()
                         Log.d("BLEStateBroadcastReceiver", "onReceive: Bluetooth is off")
                     }
 
                     BluetoothAdapter.STATE_ON -> { // 蓝牙已打开
-                        maybeSetupBluetooth()
+                        checkBluetoothPermissionAndEnable()
                         Log.d("BLEStateBroadcastReceiver", "onReceive: Bluetooth is on")
                     }
 
@@ -79,52 +86,13 @@ class XDScanBLEActivity : AppCompatActivity() {
         }
     }
 
-    private val bluetoothManager: BluetoothManager by lazy {
-        getSystemService(BLUETOOTH_SERVICE) as BluetoothManager
-    }
-
-    private var bluetoothAdapter: BluetoothAdapter? = null
-
-    private val requestMultiplePermissionLauncher by lazy {
-        registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
-            if (it.all { permission -> permission.value }) {
-                maybeSetupBluetooth()
-            } else {
-                setStatus(XDScanBLEStatus.Permission)
-            }
-        }
-    }
-
-
-    private val scanCallback = object : ScanCallback() {
-        override fun onScanResult(callbackType: Int, result: ScanResult) {
-            super.onScanResult(callbackType, result)
-            logScanResult(result)
+    private val bleConnection = object : ServiceConnection {
+        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
+            bluetoothBinder = service as XDScanBLEService.XDScanBLEBinder?
         }
 
-        override fun onBatchScanResults(results: MutableList<ScanResult>) {
-            super.onBatchScanResults(results) // 如果需要处理批量扫描结果,可以在此处进行
-
-            results.forEach { result -> logScanResult(result) }
-        }
-
-        @SuppressLint("MissingPermission")
-        private fun logScanResult(result: ScanResult) {
-            val device = result.device
-            val deviceName = device.name ?: "Unknown"
-            val deviceAddress = device.address
-            val rssi = result.rssi
-
-            //            Log.d(
-            //                "XDScanBLEService",
-            //                "发现BLE设备: 名称 - $deviceName, 地址 - $deviceAddress, 信号强度 - $rssi"
-            //            )
-            adapter.addValue(result)
-        }
-
-        override fun onScanFailed(errorCode: Int) {
-            super.onScanFailed(errorCode)
-            Log.w("XDScanBLEService", "BLE扫描失败,错误代码: $errorCode") // 根据错误码处理扫描失败情况
+        override fun onServiceDisconnected(name: ComponentName?) {
+            bluetoothBinder = null
         }
 
     }
@@ -133,112 +101,64 @@ class XDScanBLEActivity : AppCompatActivity() {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_scanble)
 
+        checkBluetoothPermissionAndEnable()
+        bindService(Intent(this, XDScanBLEService::class.java), bleConnection, 0)
+    }
+
+    override fun onResume() {
+        super.onResume()
         registerReceiver(broadcastReceiver, IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED))
+        checkBluetoothPermissionAndEnable()
+    }
+
+    override fun onPause() {
+        unregisterReceiver(broadcastReceiver)
+        super.onPause()
     }
 
-    private fun checkBluetoothPermission() {
+    private fun checkBluetoothPermissionAndEnable() {
         val bluetoothAvailable = packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
         val bluetoothLEAvailable =
             packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
 
         if (!bluetoothAvailable || !bluetoothLEAvailable) {
-            setStatus(XDScanBLEStatus.NotSupported)
+            setFragment(notsupportFragment)
             return
         }
 
-        val checkResult = permissions.find {
-            ActivityCompat.checkSelfPermission(
-                this, it
-            ) != PackageManager.PERMISSION_GRANTED
+        if (permissions.find {
+                ActivityCompat.checkSelfPermission(
+                    this, it
+                ) != PackageManager.PERMISSION_GRANTED
+            } != null) {
+            setFragment(permissionFragment)
+            return
         }
 
-        if (checkResult != null) {
-            requestMultiplePermissionLauncher.launch(permissions)
-        } else {
-            maybeSetupBluetooth()
+        if (bluetoothManager.adapter == null || !bluetoothManager.adapter.isEnabled) {
+            setFragment(disableFragment)
+            return
         }
-    }
 
-    @SuppressLint("MissingPermission")
-    private fun maybeSetupBluetooth() {
-        bluetoothAdapter = bluetoothManager.adapter
-
-        if (bluetoothAdapter == null || !bluetoothAdapter!!.isEnabled) {
-            setStatus(XDScanBLEStatus.Disabled)
-            val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
-            startActivity(enableBtIntent)
-        } else {
-            setStatus(XDScanBLEStatus.Waiting)
-        }
+        setFragment(normalFragment)
     }
 
-    @SuppressLint("MissingPermission")
-    private fun startScanBle() {
-        val settings =
-            ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) // 或选择其他适合的扫描模式
-                .build()
-
-        val filters = mutableListOf<ScanFilter>() // 可以添加过滤条件,如特定的服务UUID等
-
-        try {
-            bluetoothAdapter?.bluetoothLeScanner?.startScan(filters, settings, scanCallback)
-        } catch (e: Exception) {
-            Log.e("XDScanBLEService", "startScanBle error: ${e.message}")
+    private fun setFragment(fragment: Fragment) {
+        val fragmentManager = supportFragmentManager;
+        val beginTransaction = fragmentManager.beginTransaction()
+        if (fragmentManager.findFragmentById(R.id.fragment_container) == null) {
+            beginTransaction.add(R.id.fragment_container, fragment)
+        } else {
+            beginTransaction.replace(R.id.fragment_container, fragment)
         }
+        beginTransaction.commit()
     }
 
+    override fun onStatusChanged(status: XDScanBLEStatus) = checkBluetoothPermissionAndEnable()
+    override fun getBluetooth(): BluetoothLe =
+        bluetoothBinder?.getBluetooth() ?: throw IllegalStateException("蓝牙初始化失败")
 
-    override fun onDestroy() {
-        unregisterReceiver(broadcastReceiver)
-        super.onDestroy()
-    }
-
-    private fun setStatus(status: XDScanBLEStatus) {
-        when (status) {
-            XDScanBLEStatus.Idle -> {
-                btnScan.visibility = View.GONE
-                listview.visibility = View.GONE
-                progress.visibility = View.GONE
-                txtMsg.visibility = View.GONE
-            }
-
-            XDScanBLEStatus.Permission -> {
-                btnScan.visibility = View.GONE
-                listview.visibility = View.GONE
-                progress.visibility = View.GONE
-                txtMsg.visibility = View.VISIBLE
-                txtMsg.text = "蓝牙权限申请失败,请手动设置权限"
-            }
-
-            XDScanBLEStatus.Disabled -> {
-                btnScan.visibility = View.GONE
-                listview.visibility = View.GONE
-                progress.visibility = View.GONE
-                txtMsg.visibility = View.VISIBLE
-                txtMsg.text = "蓝牙未开启,请开启蓝牙"
-            }
-
-            XDScanBLEStatus.NotSupported -> {
-                btnScan.visibility = View.GONE
-                listview.visibility = View.GONE
-                progress.visibility = View.GONE
-                txtMsg.visibility = View.VISIBLE
-                txtMsg.text = "当前设备不支持蓝牙配对"
-            }
-
-            XDScanBLEStatus.Waiting -> {
-                btnScan.visibility = View.VISIBLE
-                listview.visibility = View.GONE
-                progress.visibility = View.GONE
-                txtMsg.visibility = View.GONE
-            }
-
-            XDScanBLEStatus.Scanning -> {
-                btnScan.visibility = View.GONE
-                listview.visibility = View.VISIBLE
-                progress.visibility = View.VISIBLE
-                txtMsg.visibility = View.GONE
-            }
-        }
+    override suspend fun connectBluetooth(device: BluetoothDevice): Boolean {
+        bluetoothBinder?.connectGatt(device)
     }
 }

+ 0 - 55
xiaodou/src/main/java/com/luojigou/xiaodou/XDScanBLEAdapter.kt

@@ -1,55 +0,0 @@
-package com.luojigou.xiaodou
-
-import android.annotation.SuppressLint
-import android.bluetooth.le.ScanResult
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.TextView
-import androidx.recyclerview.widget.RecyclerView
-
-
-@SuppressLint("MissingPermission")
-class XDScanBLEAdapter : RecyclerView.Adapter<XDScanBLEAdapter.ViewHolder>() {
-    private val list: MutableList<ScanResult> = ArrayList()
-
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
-        val itemView: View =
-            LayoutInflater.from(parent.context).inflate(R.layout.item_ble, parent, false)
-        return ViewHolder(itemView)
-    }
-
-    override fun getItemCount(): Int = list.size
-
-    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
-        val item = list[position]
-
-        holder.alias.text = item.device.name
-        holder.name.text = item.device.address
-        holder.itemView.setOnClickListener {
-            XDScanWifiActivity.start(holder.itemView.context)
-        }
-    }
-
-    fun setValues(values: List<ScanResult>) {
-        list.clear()
-        list.addAll(values)
-        notifyDataSetChanged()
-    }
-
-    fun addValue(value: ScanResult) {
-        if (value.device.name != null) {
-            if (list.firstOrNull { it.device.address == value.device.address } == null) {
-                list.add(value)
-                notifyItemChanged(list.size - 1)
-            }
-        }
-    }
-
-    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
-        val img = itemView.findViewById<ImageView>(R.id.iv_ble)
-        val alias = itemView.findViewById<TextView>(R.id.tv_ble_alias)
-        val name = itemView.findViewById<TextView>(R.id.tv_ble_name)
-    }
-}

+ 15 - 0
xiaodou/src/main/java/com/luojigou/xiaodou/XDScanBLEService.kt

@@ -5,15 +5,22 @@ import android.app.Service
 import android.content.Intent
 import android.os.Binder
 import android.os.IBinder
+import android.util.ArraySet
+import androidx.bluetooth.BluetoothDevice
 import androidx.bluetooth.BluetoothLe
 import androidx.bluetooth.ScanFilter
 import androidx.bluetooth.ScanResult
+import com.luojigou.xiaodou.ble.XDScanBLEDevice
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
 
 @SuppressLint("MissingPermission")
 class XDScanBLEService : Service() {
     private val bluetoothLe: BluetoothLe by lazy { BluetoothLe(this) }
 
+    private val deviceSet: MutableSet<XDScanBLEDevice> = ArraySet()
+
+    private val deviceListFlow = MutableSharedFlow<List<XDScanBLEDevice>(listOf())
     override fun onBind(intent: Intent?): IBinder {
         return XDScanBLEBinder(this)
     }
@@ -25,8 +32,16 @@ class XDScanBLEService : Service() {
             )
         }
 
+        fun getBluetooth(): BluetoothLe = service.bluetoothLe
+
         suspend fun scanBle(): Flow<ScanResult> {
             return service.bluetoothLe.scan(filter)
         }
+
+        suspend fun connectGatt(device: BluetoothDevice) {
+            service.bluetoothLe.connectGatt(device) {
+
+            }
+        }
     }
 }

+ 0 - 13
xiaodou/src/main/java/com/luojigou/xiaodou/XDScanBLEStatus.kt

@@ -1,13 +0,0 @@
-package com.luojigou.xiaodou
-
-sealed class XDScanBLEStatus {
-    object Idle : XDScanBLEStatus()
-    sealed class Error : XDScanBLEStatus()
-
-    object Permission : Error()
-    object Disabled : Error()
-    object NotSupported : Error()
-
-    object Waiting : XDScanBLEStatus()
-    object Scanning : XDScanBLEStatus()
-}

+ 5 - 0
xiaodou/src/main/java/com/luojigou/xiaodou/ble/BLEConnectStatus.kt

@@ -0,0 +1,5 @@
+package com.luojigou.xiaodou.ble
+
+class BLEConnectStatus {
+
+}

+ 66 - 0
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEAdapter.kt

@@ -0,0 +1,66 @@
+package com.luojigou.xiaodou.ble
+
+import android.annotation.SuppressLint
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.collection.ArraySet
+import androidx.recyclerview.widget.RecyclerView
+import com.luojigou.xiaodou.R
+
+
+@SuppressLint("MissingPermission")
+class XDScanBLEAdapter(
+    private val itemClickListener: (Item) -> Unit,
+) : RecyclerView.Adapter<XDScanBLEAdapter.ViewHolder>() {
+    private val list: MutableSet<Item> = ArraySet()
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+        val itemView: View =
+            LayoutInflater.from(parent.context).inflate(R.layout.item_ble, parent, false)
+        return ViewHolder(itemView)
+    }
+
+    override fun getItemCount(): Int = list.size
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        val item = list.elementAt(position)
+
+        holder.apply {
+            id.text = item.id
+            name.text = item.name
+            bondState.text = item.bondState
+            rssi.text = item.rssi
+            address.text = item.address
+            addressType.text = item.addressType
+        }
+
+        holder.itemView.setOnClickListener {
+            itemClickListener(item)
+        }
+    }
+
+    @SuppressLint("NotifyDataSetChanged")
+    fun setValues(values: List<Item>) {
+        list.clear()
+        list.addAll(values)
+        notifyDataSetChanged()
+    }
+
+    fun addValue(value: Item) {
+        list.add(value)
+        notifyItemChanged(list.size - 1)
+    }
+
+    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+        val img = itemView.findViewById<ImageView>(R.id.iv_ble)
+        val id = itemView.findViewById<TextView>(R.id.tv_ble_id)
+        val name = itemView.findViewById<TextView>(R.id.tv_ble_name)
+        val bondState = itemView.findViewById<TextView>(R.id.tv_ble_bond_tate)
+        val rssi = itemView.findViewById<TextView>(R.id.tv_ble_rssi)
+        val address = itemView.findViewById<TextView>(R.id.tv_ble_address)
+        val addressType = itemView.findViewById<TextView>(R.id.tv_ble_address_type)
+    }
+}

+ 21 - 0
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEDevice.kt

@@ -0,0 +1,21 @@
+package com.luojigou.xiaodou.ble
+data class XDScanBLEDevice(
+    val id: String,
+    val name: String,
+    val bondState: String,
+    val rssi: String,
+    val address: String,
+    val addressType: String,
+) {
+    override fun hashCode(): Int {
+        return address.hashCode()
+    }
+
+    override fun equals(other: Any?): Boolean {
+        return if (other is XDScanBLEDevice) {
+            address == other.address
+        } else {
+            false
+        }
+    }
+}

+ 6 - 5
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEDisableFragment.kt

@@ -15,20 +15,21 @@ import com.luojigou.xiaodou.R
 
 @SuppressLint("MissingPermission")
 class XDScanBLEDisableFragment(private val host: XDScanBLEStatus.Host) : Fragment() {
-    private val openBle: ActivityResultLauncher<Intent> =
-        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
-            host.onStatusChanged(XDScanBLEStatus.Disabled)
-        }
+    private lateinit var openBle: ActivityResultLauncher<Intent>
 
     override fun onCreateView(
         inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
     ): View? {
-        return inflater.inflate(R.layout.fragment_scanwifi_disable, container, false)
+        return inflater.inflate(R.layout.fragment_scanble_disable, container, false)
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
+        openBle = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
+            host.onStatusChanged(XDScanBLEStatus.Disabled)
+        }
+
         val button = view.findViewById<Button>(R.id.btn_open)
         button.setOnClickListener { checkAndOpenBle() }
     }

+ 70 - 6
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLENormalFragment.kt

@@ -1,36 +1,100 @@
 package com.luojigou.xiaodou.ble
 
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Intent
 import android.os.Bundle
+import android.util.Log
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.bluetooth.ScanFilter
 import androidx.fragment.app.Fragment
 import androidx.recyclerview.widget.GridLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.luojigou.xiaodou.R
-import com.luojigou.xiaodou.XDScanBLEAdapter
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 
-class XDScanBLENormalFragment(private val host: XDScanBLEStatus.Host) : Fragment() {
-    private val adapter = XDScanBLEAdapter()
+@SuppressLint("MissingPermission")
+class XDScanBLENormalFragment(private val host: XDScanBLEStatus.Host) : Fragment(),
+    CoroutineScope by MainScope() {
+    private val adapter = XDScanBLEAdapter {
 
-    private val layoutManager by lazy {
-        GridLayoutManager(requireContext(), 2, RecyclerView.VERTICAL, false)
     }
 
+    private val scanFilter = listOf<ScanFilter>(
+    )
+
+    private lateinit var selectWifi: ActivityResultLauncher<Intent>
+
     override fun onCreateView(
         inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
     ): View? {
-        return super.onCreateView(inflater, container, savedInstanceState)
+        return inflater.inflate(R.layout.fragment_scanble_normal, container, false)
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
+        selectWifi = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
+            host.onStatusChanged(XDScanBLEStatus.Disabled)
+        }
+
         val recyclerView = view.findViewById<RecyclerView>(R.id.scan_list)
+        val layoutManager = GridLayoutManager(requireContext(), 2, RecyclerView.VERTICAL, false)
 
         recyclerView.layoutManager = layoutManager
         recyclerView.adapter = adapter
     }
 
+    override fun onAttach(context: Context) {
+        super.onAttach(context)
+
+        launch {
+            host.getBluetooth().scan(scanFilter).collect {
+                val device = it.device
+                val rssi = it.rssi
+                val serviceUuids = it.serviceUuids
+                val deviceAddress = it.deviceAddress
+                val periodicAdvertisingInterval = it.periodicAdvertisingInterval
+                val timestampNanos = it.timestampNanos
+                val serviceData = it.serviceData
+
+                val id = device.id
+                val bondState = device.bondState
+                val name = device.name
 
+                val address = deviceAddress.address
+                val addressType = deviceAddress.addressType
+
+                Log.d("XDScanBLENormalFragment", "onAttach: ")
+
+                if (name != null) {
+                    withContext(Dispatchers.Main) {
+                        adapter.addValue(
+                            XDScanBLEAdapter.Item(
+                                id = id.toString(),
+                                name = name.toString(),
+                                bondState = bondState.toString(),
+                                rssi = rssi.toString(),
+                                address = address,
+                                addressType = addressType.toString()
+                            )
+                        )
+                    }
+                }
+            }
+        }
+    }
+
+    override fun onDetach() {
+        adapter.setValues(mutableListOf())
+        super.onDetach()
+    }
 }

+ 13 - 0
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLENotSupportFragment.kt

@@ -1,7 +1,20 @@
 package com.luojigou.xiaodou.ble
 
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
 import androidx.fragment.app.Fragment
+import com.luojigou.xiaodou.R
 
 class XDScanBLENotSupportFragment(private val host: XDScanBLEStatus.Host) : Fragment() {
+    override fun onCreateView(
+        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(R.layout.fragment_scanble_not_support, container, false)
+    }
 
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+    }
 }

+ 11 - 10
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEPermissionFragment.kt

@@ -14,15 +14,7 @@ import androidx.fragment.app.Fragment
 import com.luojigou.xiaodou.R
 
 class XDScanBLEPermissionFragment(private val host: XDScanBLEStatus.Host) : Fragment() {
-    private val requestPermission: ActivityResultLauncher<Array<String>> =
-        registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
-            if (it.all { permission -> permission.value }) {
-                host.onStatusChanged(XDScanBLEStatus.Normal)
-            } else {
-                Log.e("XDScanWifiActivity", "requestPermission: 权限被拒绝")
-            }
-        }
-
+    private lateinit var requestPermission: ActivityResultLauncher<Array<String>>
 
     private val permissions: Array<String> by lazy {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@@ -41,12 +33,21 @@ class XDScanBLEPermissionFragment(private val host: XDScanBLEStatus.Host) : Frag
     override fun onCreateView(
         inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
     ): View? {
-        return inflater.inflate(R.layout.fragment_scanwifi_disable, container, false)
+        return inflater.inflate(R.layout.fragment_scanble_permission, container, false)
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
+        requestPermission =
+            registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
+                if (it.all { permission -> permission.value }) {
+                    host.onStatusChanged(XDScanBLEStatus.Normal)
+                } else {
+                    Log.e("XDScanWifiActivity", "requestPermission: 权限被拒绝")
+                }
+            }
+
         val button = view.findViewById<Button>(R.id.btn_open)
         button.setOnClickListener { requestPermission() }
     }

+ 5 - 2
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEStatus.kt

@@ -1,6 +1,7 @@
 package com.luojigou.xiaodou.ble
 
-import android.net.wifi.WifiManager
+import androidx.bluetooth.BluetoothDevice
+import androidx.bluetooth.BluetoothLe
 
 sealed class XDScanBLEStatus {
     object Disabled : XDScanBLEStatus()
@@ -11,6 +12,8 @@ sealed class XDScanBLEStatus {
     interface Host {
         fun onStatusChanged(status: XDScanBLEStatus)
 
-        fun getWifiManager(): WifiManager
+        fun getBluetooth(): BluetoothLe
+
+        suspend fun connectBluetooth(device: BluetoothDevice): Boolean
     }
 }

+ 5 - 5
xiaodou/src/main/java/com/luojigou/xiaodou/XDScanWifiAdapter.kt → xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiAdapter.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou
+package com.luojigou.xiaodou.wifi
 
 import android.net.wifi.ScanResult
 import android.view.LayoutInflater
@@ -7,13 +7,14 @@ import android.view.ViewGroup
 import android.widget.ImageView
 import android.widget.TextView
 import androidx.recyclerview.widget.RecyclerView
+import com.luojigou.xiaodou.R
 
 class XDScanWifiAdapter : RecyclerView.Adapter<XDScanWifiAdapter.ViewHolder>() {
     private val list: MutableList<ScanResult> = ArrayList()
 
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
         val itemView: View =
-            LayoutInflater.from(parent.context).inflate(R.layout.item_ble, parent, false)
+            LayoutInflater.from(parent.context).inflate(R.layout.item_wifi, parent, false)
         return ViewHolder(itemView)
     }
 
@@ -41,8 +42,7 @@ class XDScanWifiAdapter : RecyclerView.Adapter<XDScanWifiAdapter.ViewHolder>() {
     }
 
     class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
-        val img = itemView.findViewById<ImageView>(R.id.iv_ble)
-        val alias = itemView.findViewById<TextView>(R.id.tv_ble_alias)
-        val name = itemView.findViewById<TextView>(R.id.tv_ble_name)
+        val img = itemView.findViewById<ImageView>(R.id.iv_wifi_rssi)
+        val name = itemView.findViewById<TextView>(R.id.tv_wifi_name)
     }
 }

+ 0 - 1
xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiNormalFragment.kt

@@ -13,7 +13,6 @@ import android.view.ViewGroup
 import androidx.fragment.app.Fragment
 import androidx.recyclerview.widget.LinearLayoutManager
 import com.luojigou.xiaodou.R
-import com.luojigou.xiaodou.XDScanWifiAdapter
 
 @SuppressLint("MissingPermission")
 class XDScanWifiNormalFragment(private val host: XDScanWifiStatus.Host) : Fragment() {

+ 4 - 1
xiaodou/src/main/res/layout/fragment_scanble_normal.xml

@@ -2,5 +2,8 @@
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
-
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/scan_list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 1 - 1
xiaodou/src/main/res/layout/fragment_scanble_permission.xml

@@ -25,6 +25,6 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
             android:layout_marginVertical="16dp"
-            android:text="去打开" />
+            android:text="去授予" />
     </LinearLayout>
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 1 - 1
xiaodou/src/main/res/layout/fragment_scanwifi_permission.xml

@@ -25,6 +25,6 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
             android:layout_marginVertical="16dp"
-            android:text="去打开" />
+            android:text="去授予" />
     </LinearLayout>
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 34 - 6
xiaodou/src/main/res/layout/item_ble.xml

@@ -7,19 +7,47 @@
     <ImageView
         android:id="@+id/iv_ble"
         android:layout_width="match_parent"
-        android:layout_height="200dp" />
+        android:layout_height="100dp" />
 
     <TextView
-        android:id="@+id/tv_ble_alias"
+        android:id="@+id/tv_ble_id"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal"
-        android:text="adadafafafaf" />
+        android:layout_gravity="start"
+        android:text="" />
 
     <TextView
         android:id="@+id/tv_ble_name"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal"
-        android:text="111223" />
+        android:layout_gravity="start"
+        android:text="" />
+
+    <TextView
+        android:id="@+id/tv_ble_bond_tate"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="start"
+        android:text="" />
+
+    <TextView
+        android:id="@+id/tv_ble_rssi"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="start"
+        android:text="" />
+
+    <TextView
+        android:id="@+id/tv_ble_address"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="start"
+        android:text="" />
+
+    <TextView
+        android:id="@+id/tv_ble_address_type"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="start"
+        android:text="" />
 </LinearLayout>

+ 19 - 1
xiaodou/src/main/res/layout/item_wifi.xml

@@ -1,6 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="48dp">
 
+    <ImageView
+        android:id="@+id/iv_wifi_rssi"
+        android:layout_width="48dp"
+        android:layout_height="0dp"
+        android:contentDescription="wifi rssi"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_wifi_name"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toRightOf="@id/iv_wifi_rssi"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
 </androidx.constraintlayout.widget.ConstraintLayout>