2 Commits f9939e958e ... e2b3c820c0

Tác giả SHA1 Thông báo Ngày
  zhaoyadi e2b3c820c0 add introduce 8 tháng trước cách đây
  zhaoyadi 34926a0d79 migrate commit 8 tháng trước cách đây
65 tập tin đã thay đổi với 1086 bổ sung297 xóa
  1. 0 1
      .idea/codeStyles/Project.xml
  2. 0 1
      .idea/misc.xml
  3. 1 1
      demo/src/main/AndroidManifest.xml
  4. 5 1
      xiaodou/build.gradle
  5. 15 3
      xiaodou/src/main/AndroidManifest.xml
  6. 90 0
      xiaodou/src/main/java/com/luojigou/product/ProductSelectActivity.kt
  7. 24 0
      xiaodou/src/main/java/com/luojigou/product/base/BaseActivity.kt
  8. 104 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/XDConnectActivity.kt
  9. 57 47
      xiaodou/src/main/java/com/luojigou/product/xiaodou/XDConnectService.kt
  10. 31 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/XDIntroduceActivity.kt
  11. 15 13
      xiaodou/src/main/java/com/luojigou/product/xiaodou/XDScanBLEActivity.kt
  12. 18 11
      xiaodou/src/main/java/com/luojigou/product/xiaodou/XDScanWifiActivity.kt
  13. 1 1
      xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDBLEConnectStatus.kt
  14. 1 1
      xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDBLEController.kt
  15. 2 1
      xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDBLEUtils.kt
  16. 8 16
      xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEAdapter.kt
  17. 6 2
      xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEDevice.kt
  18. 2 2
      xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEDisableFragment.kt
  19. 9 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEGattCallback.kt
  20. 19 13
      xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLENormalFragment.kt
  21. 2 2
      xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLENotSupportFragment.kt
  22. 2 2
      xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEPermissionFragment.kt
  23. 1 1
      xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEStatus.kt
  24. 18 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectConnectingFragment.kt
  25. 18 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectErrorFragment.kt
  26. 18 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectFailFragment.kt
  27. 18 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectNotFoundFragment.kt
  28. 18 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectPasswordErrorFragment.kt
  29. 18 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectSuccessFragment.kt
  30. 18 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectTimeoutFragment.kt
  31. 81 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiAdapter.kt
  32. 2 2
      xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiDisableFragment.kt
  33. 1 1
      xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiEntity.kt
  34. 1 1
      xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiInfo.kt
  35. 34 16
      xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiNormalFragment.kt
  36. 2 2
      xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiPasswordFragment.kt
  37. 47 0
      xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiPasswordWithSsidFragment.kt
  38. 2 2
      xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiPermissionFragment.kt
  39. 1 1
      xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiStatus.kt
  40. 0 15
      xiaodou/src/main/java/com/luojigou/xiaodou/XDBindFailureActivity.kt
  41. 0 11
      xiaodou/src/main/java/com/luojigou/xiaodou/XDBindSuccessActivity.kt
  42. 0 4
      xiaodou/src/main/java/com/luojigou/xiaodou/XDConnectActivity.kt
  43. 0 13
      xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEGattCallback.kt
  44. 0 58
      xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiAdapter.kt
  45. 24 0
      xiaodou/src/main/res-xiaodou/layout/activity_xd_introduce.xml
  46. 27 0
      xiaodou/src/main/res/drawable/ic_lock.xml
  47. 9 0
      xiaodou/src/main/res/drawable/xiaodou.xml
  48. 0 6
      xiaodou/src/main/res/layout/activity_bind_failure.xml
  49. 0 6
      xiaodou/src/main/res/layout/activity_bind_success.xml
  50. 12 0
      xiaodou/src/main/res/layout/activity_connect.xml
  51. 11 0
      xiaodou/src/main/res/layout/activity_product_select.xml
  52. 29 0
      xiaodou/src/main/res/layout/fragment_connect_connecting.xml
  53. 29 0
      xiaodou/src/main/res/layout/fragment_connect_error.xml
  54. 31 0
      xiaodou/src/main/res/layout/fragment_connect_fail.xml
  55. 31 0
      xiaodou/src/main/res/layout/fragment_connect_not_found.xml
  56. 29 0
      xiaodou/src/main/res/layout/fragment_connect_password_error.xml
  57. 29 0
      xiaodou/src/main/res/layout/fragment_connect_success.xml
  58. 29 0
      xiaodou/src/main/res/layout/fragment_connect_timeout.xml
  59. 8 0
      xiaodou/src/main/res/layout/fragment_scanble_normal.xml
  60. 1 1
      xiaodou/src/main/res/layout/fragment_scanwifi_password.xml
  61. 26 0
      xiaodou/src/main/res/layout/fragment_scanwifi_password_with_ssid.xml
  62. 4 37
      xiaodou/src/main/res/layout/item_ble.xml
  63. 20 0
      xiaodou/src/main/res/layout/item_product.xml
  64. 22 1
      xiaodou/src/main/res/layout/item_wifi_add.xml
  65. 5 1
      xiaodou/src/main/res/values/themes.xml

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

@@ -1,7 +1,6 @@
 <component name="ProjectCodeStyleConfiguration">
   <code_scheme name="Project" version="173">
     <JetCodeStyleSettings>
-      <option name="WRAP_EXPRESSION_BODY_FUNCTIONS" value="2" />
       <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
     </JetCodeStyleSettings>
     <codeStyleSettings language="Dart">

+ 0 - 1
.idea/misc.xml

@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="ExternalStorageConfigurationManager" enabled="true" />
   <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">

+ 1 - 1
demo/src/main/AndroidManifest.xml

@@ -10,7 +10,7 @@
         android:theme="@style/Theme.Xiaodou">
 
         <activity
-            android:name="com.luojigou.xiaodou.XDScanBLEActivity"
+            android:name="com.luojigou.product.ProductSelectActivity"
             android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />

+ 5 - 1
xiaodou/build.gradle

@@ -5,7 +5,7 @@ plugins {
 }
 
 android {
-    namespace 'com.luojigou.xiaodou'
+    namespace 'com.luojigou.product'
     compileSdk 33
 
     defaultConfig {
@@ -33,6 +33,10 @@ android {
                     'libs',
                     'src/main/cpp/libs'
             ]
+
+            res{
+                srcDir("src/main/res-xiaodou")
+            }
         }
     }
     buildFeatures {

+ 15 - 3
xiaodou/src/main/AndroidManifest.xml

@@ -39,15 +39,27 @@
 
     <application>
         <activity
-            android:name=".XDScanBLEActivity"
+            android:name=".ProductSelectActivity"
             android:theme="@style/XDTheme" />
 
         <activity
-            android:name=".XDScanWifiActivity"
+            android:name=".xiaodou.XDScanBLEActivity"
+            android:theme="@style/XDTheme" />
+
+        <activity
+            android:name=".xiaodou.XDScanWifiActivity"
+            android:theme="@style/XDTheme" />
+
+        <activity
+            android:name=".xiaodou.XDConnectActivity"
+            android:theme="@style/XDTheme" />
+
+        <activity
+            android:name=".xiaodou.XDIntroduceActivity"
             android:theme="@style/XDTheme" />
 
         <service
-            android:name=".XDScanBLEService"
+            android:name=".xiaodou.XDConnectService"
             android:exported="false"
             android:foregroundServiceType="connectedDevice" />
     </application>

+ 90 - 0
xiaodou/src/main/java/com/luojigou/product/ProductSelectActivity.kt

@@ -0,0 +1,90 @@
+package com.luojigou.product
+
+import android.content.Intent
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.luojigou.product.base.BaseActivity
+import com.luojigou.product.xiaodou.XDIntroduceActivity
+import com.google.android.material.R.drawable as MaterialDrawable
+
+class ProductSelectActivity : BaseActivity() {
+    private lateinit var productAdapter: ProductAdapter
+    private lateinit var productLayoutManager: GridLayoutManager
+    private lateinit var productRecyclerView: RecyclerView
+
+    private val productList = listOf(
+        ProductModel(0, "小逗AI学习机", MaterialDrawable.ic_clock_black_24dp),
+        ProductModel(1, "中逗AI学习机", MaterialDrawable.ic_keyboard_black_24dp),
+        ProductModel(2, "大逗AI学习机", MaterialDrawable.material_ic_calendar_black_24dp),
+    )
+
+    override fun onCreate(savedInstanceState: android.os.Bundle?) {
+        super.onCreate(savedInstanceState)
+        setTitle("支持的设备列表")
+
+        productRecyclerView = findViewById(R.id.rv_product_list)
+
+        productAdapter = ProductAdapter(productList)
+        productAdapter.setOnItemClickListener { p ->
+            when (p.id) {
+                0 -> startActivity(Intent(this, XDIntroduceActivity::class.java))
+                1 -> { // TODO: 跳转到中逗AI学习机
+                }
+
+                2 -> { // TODO: 跳转到大逗AI学习机
+                }
+            }
+        }
+        productLayoutManager = GridLayoutManager(this, 2)
+        productRecyclerView.layoutManager = productLayoutManager
+        productRecyclerView.adapter = productAdapter
+    }
+
+    override fun getLayoutId(): Int = R.layout.activity_product_select
+
+    class ProductAdapter() : RecyclerView.Adapter<ViewHolder>() {
+        private val dataList = ArrayList<ProductModel>()
+
+        private var onItemClickListener: ((ProductModel) -> Unit)? = null
+
+        constructor(list: List<ProductModel>) : this() {
+            dataList.addAll(list)
+        }
+
+        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+            val itemView = LayoutInflater.from(parent.context)
+                .inflate(R.layout.item_product, parent, false)
+            return ViewHolder(itemView)
+        }
+
+        override fun getItemCount(): Int = dataList.size
+
+        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+            val product = dataList[position]
+            holder.name.text = product.name
+            holder.img.setImageResource(product.icon)
+
+            holder.itemView.setOnClickListener {
+                onItemClickListener?.invoke(product)
+            }
+        }
+
+        fun setOnItemClickListener(listener: (ProductModel) -> Unit) {
+            onItemClickListener = listener
+        }
+    }
+
+    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+        val name = itemView.findViewById<android.widget.TextView>(R.id.tv_product_name)
+        val img = itemView.findViewById<android.widget.ImageView>(R.id.iv_product_img)
+    }
+
+    data class ProductModel(
+        val id: Int,
+        val name: String,
+        val icon: Int,
+    )
+}

+ 24 - 0
xiaodou/src/main/java/com/luojigou/product/base/BaseActivity.kt

@@ -0,0 +1,24 @@
+package com.luojigou.product.base
+
+import android.graphics.drawable.ColorDrawable
+import android.os.Bundle
+import androidx.annotation.LayoutRes
+import androidx.appcompat.app.AppCompatActivity
+
+abstract class BaseActivity : AppCompatActivity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(getLayoutId())
+    }
+
+    @LayoutRes
+    protected abstract fun getLayoutId(): Int
+
+    protected fun setTitle(title: String) {
+        supportActionBar?.run {
+            this.title = title
+            this.setDisplayHomeAsUpEnabled(true)
+            this.setBackgroundDrawable(ColorDrawable(0x00000000))
+        }
+    }
+}

+ 104 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/XDConnectActivity.kt

@@ -0,0 +1,104 @@
+package com.luojigou.product.xiaodou
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Bundle
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import com.luojigou.product.R
+import com.luojigou.product.base.BaseActivity
+import com.luojigou.product.xiaodou.connect.XDConnectConnectingFragment
+import com.luojigou.product.xiaodou.connect.XDConnectErrorFragment
+import com.luojigou.product.xiaodou.connect.XDConnectFailFragment
+import com.luojigou.product.xiaodou.connect.XDConnectNotFoundFragment
+import com.luojigou.product.xiaodou.connect.XDConnectPasswordErrorFragment
+import com.luojigou.product.xiaodou.connect.XDConnectSuccessFragment
+import com.luojigou.product.xiaodou.connect.XDConnectTimeoutFragment
+import com.luojigou.product.xiaodou.wifi.XDScanWifiInfo
+
+class XDConnectActivity : BaseActivity() {
+    companion object {
+        fun startConnect(context: Context, device: XDScanWifiInfo) {
+            val intent = Intent(context, XDConnectActivity::class.java)
+            intent.putExtra(XDConnectService.ACTION_SELECT_WIFI_DEVICE_DATA, device)
+            context.startActivity(intent)
+        }
+    }
+
+    private val timeoutFragment = XDConnectTimeoutFragment()
+    private val errorFragment = XDConnectErrorFragment()
+    private val successFragment = XDConnectSuccessFragment()
+    private val connectingFragment = XDConnectConnectingFragment()
+    private val failFragment = XDConnectFailFragment()
+    private val notFoundFragment = XDConnectNotFoundFragment()
+    private val passwordErrorFragment = XDConnectPasswordErrorFragment()
+
+    private val connectReceiver = object : BroadcastReceiver() {
+        override fun onReceive(context: Context?, intent: Intent) {
+            setFragment(
+                when (intent.action) {
+                    XDConnectService.ACTION_CONNECT_WIFI_RESULT_TIMEOUT -> timeoutFragment
+                    XDConnectService.ACTION_CONNECT_WIFI_RESULT_ERROR -> errorFragment
+                    XDConnectService.ACTION_CONNECT_WIFI_RESULT_SUCCESS -> successFragment
+                    XDConnectService.ACTION_CONNECT_WIFI_RESULT_CONNECTING -> connectingFragment
+                    XDConnectService.ACTION_CONNECT_WIFI_RESULT_FAIL -> failFragment
+                    XDConnectService.ACTION_CONNECT_WIFI_RESULT_NOT_FOUND -> notFoundFragment
+                    XDConnectService.ACTION_CONNECT_WIFI_RESULT_PASSWORD_ERROR -> passwordErrorFragment
+                    else -> errorFragment
+                }
+            )
+        }
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setTitle("连接Wi-Fi")
+        setFragment(connectingFragment)
+
+        val intentFilter = IntentFilter()
+        intentFilter.apply {
+            addAction(XDConnectService.ACTION_CONNECT_WIFI_RESULT_TIMEOUT)
+            addAction(XDConnectService.ACTION_CONNECT_WIFI_RESULT_ERROR)
+            addAction(XDConnectService.ACTION_CONNECT_WIFI_RESULT_SUCCESS)
+            addAction(XDConnectService.ACTION_CONNECT_WIFI_RESULT_CONNECTING)
+            addAction(XDConnectService.ACTION_CONNECT_WIFI_RESULT_FAIL)
+            addAction(XDConnectService.ACTION_CONNECT_WIFI_RESULT_NOT_FOUND)
+            addAction(XDConnectService.ACTION_CONNECT_WIFI_RESULT_PASSWORD_ERROR)
+        }
+
+        ContextCompat.registerReceiver(
+            this,
+            connectReceiver,
+            intentFilter,
+            ContextCompat.RECEIVER_EXPORTED,
+        )
+
+        val device = intent.getParcelableExtra<XDScanWifiInfo>(XDConnectService.ACTION_SELECT_WIFI_DEVICE_DATA)
+
+        if (device != null) {
+            val intent = Intent(XDConnectService.ACTION_SELECT_WIFI_DEVICE)
+            intent.putExtra(XDConnectService.ACTION_SELECT_WIFI_DEVICE_DATA, device)
+            sendBroadcast(intent)
+        }
+    }
+
+    override fun getLayoutId(): Int = R.layout.activity_connect
+
+    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 onDestroy() {
+        unregisterReceiver(connectReceiver)
+        super.onDestroy()
+    }
+}

+ 57 - 47
xiaodou/src/main/java/com/luojigou/xiaodou/XDScanBLEService.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/XDConnectService.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou
+package com.luojigou.product.xiaodou
 
 import android.annotation.SuppressLint
 import android.app.Service
@@ -25,15 +25,15 @@ import androidx.core.app.NotificationChannelCompat
 import androidx.core.app.NotificationCompat
 import androidx.core.app.NotificationManagerCompat
 import androidx.core.content.ContextCompat
-import com.luojigou.xiaodou.ble.XDBLEUtils
-import com.luojigou.xiaodou.ble.XDScanBLEDevice
-import com.luojigou.xiaodou.wifi.XDScanWifiInfo
+import com.luojigou.product.xiaodou.ble.XDBLEUtils
+import com.luojigou.product.xiaodou.ble.XDScanBLEDevice
+import com.luojigou.product.xiaodou.wifi.XDScanWifiInfo
 import java.util.UUID
 import kotlin.concurrent.thread
 
 
 @SuppressLint("MissingPermission")
-class XDScanBLEService : Service() {
+class XDConnectService : Service() {
     companion object {
         const val ACTION_START_SCAN = "com.luojigou.xiaodou.ble.ACTION_START_SCAN"
         const val ACTION_STOP_SCAN = "com.luojigou.xiaodou.ble.ACTION_STOP_SCAN"
@@ -52,9 +52,15 @@ class XDScanBLEService : Service() {
         const val ACTION_CONNECT_BLE_RESULT_SUCCESS = "com.luojigou.xiaodou.ble.ACTION_CONNECT_BLE_RESULT_SUCCESS"
 
         const val ACTION_CONNECT_WIFI = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI"
-        const val ACTION_CONNECT_WIFI_RESULT_ERROR = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_ERROR"
-        const val ACTION_CONNECT_WIFI_RESULT_SUCCESS = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_SUCCESS"
-
+        const val ACTION_CONNECT_WIFI_RESULT_TIMEOUT = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_TIMEOUT" // -2
+        const val ACTION_CONNECT_WIFI_RESULT_ERROR = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_ERROR" // -1
+        const val ACTION_CONNECT_WIFI_RESULT_SUCCESS = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_SUCCESS" // 0
+        const val ACTION_CONNECT_WIFI_RESULT_CONNECTING = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_CONNECTING" // 1
+        const val ACTION_CONNECT_WIFI_RESULT_FAIL = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_FAIL" // 2
+        const val ACTION_CONNECT_WIFI_RESULT_NOT_FOUND = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_NOT_FOUND" // 3
+        const val ACTION_CONNECT_WIFI_RESULT_PASSWORD_ERROR = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_PASSWORD_ERROR" // 4
+
+        private val deviceServiceUuidMask = UUID.fromString("0000af00-0000-1000-8000-00805f9b34fb")
         private val wifiConnectServiceUUID = UUID.fromString("0000ae80-0000-1000-8000-00805f9b34fb")
         private val wifiConnectWriteUUID = UUID.fromString("0000ae81-0000-1000-8000-00805f9b34fb")
         private val wifiConnectNotifyUUID = UUID.fromString("0000ae82-0000-1000-8000-00805f9b34fb")
@@ -63,7 +69,7 @@ class XDScanBLEService : Service() {
         private val bleChannelName = "BLE-CHANNEL"
     }
 
-    private val bluetoothDevices: MutableMap<XDScanBLEDevice, BluetoothDevice> = HashMap()
+    private val bluetoothDevices: MutableList<XDScanBLEDevice> = mutableListOf()
 
     private lateinit var bluetoothManager: BluetoothManager
 
@@ -84,10 +90,11 @@ class XDScanBLEService : Service() {
                 ACTION_SELECT_BLE_DEVICE -> {
                     val bleDevice = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                         intent.getParcelableExtra(
-                            ACTION_SELECT_BLE_DEVICE_DATA, XDScanBLEDevice::class.java
+                            ACTION_SELECT_BLE_DEVICE_DATA,
+                            XDScanBLEDevice::class.java
                         )
                     } else {
-                        intent.getParcelableExtra<XDScanBLEDevice>(ACTION_SELECT_BLE_DEVICE)
+                        intent.getParcelableExtra(ACTION_SELECT_BLE_DEVICE)
                     }
 
                     bleDevice?.let { connectBLE(it) }
@@ -104,6 +111,10 @@ class XDScanBLEService : Service() {
 
                     wifiInfo?.let { connectWifi(wifiInfo) }
                 }
+
+                ACTION_CONNECT_WIFI -> {
+
+                }
             }
         }
     }
@@ -150,19 +161,21 @@ class XDScanBLEService : Service() {
             result.apply {
                 if (device.name == null) return
 
+                if (!device.name.startsWith("XiaoDouAI")) return
+
                 val device = XDScanBLEDevice(
                     name = device.name ?: "unknown",
                     bondState = device.bondState.toString(),
                     rssi = rssi.toString(),
                     address = device.address,
                     addressType = device.type.toString(),
+                    device = device
                 )
 
-                if (!bluetoothDevices.contains(device)) {
-                    bluetoothDevices[device] = result.device
+                if (bluetoothDevices.firstOrNull { it.address == device.address } == null) {
+                    bluetoothDevices.add(device)
                 }
             }
-
         }
     }
 
@@ -251,14 +264,15 @@ class XDScanBLEService : Service() {
     private fun sendResult() {
         val intent = Intent(ACTION_SCAN_RESULT)
         intent.putParcelableArrayListExtra(
-            ACTION_SCAN_RESULT_DATA, ArrayList(bluetoothDevices.keys)
+            ACTION_SCAN_RESULT_DATA, ArrayList(bluetoothDevices)
         )
         sendBroadcast(intent)
     }
 
     private fun connectBLE(device: XDScanBLEDevice) {
         broadcastUpdate(ACTION_CONNECT_BLE)
-        val bleDevice = bluetoothDevices[device] ?: return
+        val bleDevice = bluetoothDevices.firstOrNull { it.address == device.address }?.device
+            ?: return
 
         bluetoothGatt = bleDevice.connectGatt(
             this,
@@ -271,11 +285,19 @@ class XDScanBLEService : Service() {
     private fun connectWifi(device: XDScanWifiInfo) {
         if (bluetoothGatt == null || writeCharacteristic == null) return
 
-        bluetoothGatt!!.writeCharacteristic(
-            writeCharacteristic!!,
-            XDBLEUtils.convertToConnectRequest(device.ssid, device.password),
-            BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE,
+        val bytes = XDBLEUtils.convertToConnectRequest(
+            device.ssid, device.password
         )
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+            bluetoothGatt!!.writeCharacteristic(
+                writeCharacteristic!!,
+                bytes, BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE,
+            )
+        } else {
+            writeCharacteristic!!.setValue(bytes)
+            bluetoothGatt!!.writeCharacteristic(writeCharacteristic!!)
+        }
     }
 
     override fun onDestroy() {
@@ -341,31 +363,13 @@ class XDScanBLEService : Service() {
             }
         }
 
-        override fun onCharacteristicChanged(
-            gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic
-        ) {
-            super.onCharacteristicChanged(gatt, characteristic)
-            gatt.readCharacteristic(characteristic)
-            Log.d("XDScanBLEService", "onCharacteristicChanged1:")
-        }
-
         override fun onCharacteristicChanged(
             gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray
         ) {
             super.onCharacteristicChanged(gatt, characteristic, value)
-            val result = XDBLEUtils.parseConnectResponse(value)
-            Log.d("XDScanBLEService", "onCharacteristicChanged2: $result")
-        }
-
-        override fun onCharacteristicRead(
-            gatt: BluetoothGatt,
-            characteristic: BluetoothGattCharacteristic,
-            value: ByteArray,
-            status: Int
-        ) {
-            super.onCharacteristicRead(gatt, characteristic, value, status)
-            val result = XDBLEUtils.parseConnectResponse(value)
-            Log.d("XDScanBLEService", "onCharacteristicRead: $result")
+            val response = XDBLEUtils.parseConnectResponse(value)
+            response.toAction()
+            Log.d("XDScanBLEService", "onCharacteristicChanged: $response")
         }
 
         override fun onCharacteristicWrite(
@@ -377,13 +381,19 @@ class XDScanBLEService : Service() {
                 Log.d("XDScanBLEService", "onCharacteristicWrite: success")
             }
         }
+    }
 
-        override fun onDescriptorRead(
-            gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int, value: ByteArray
-        ) {
-            super.onDescriptorRead(gatt, descriptor, status, value)
-            val result = XDBLEUtils.parseConnectResponse(value)
-            Log.d("XDScanBLEService", "onDescriptorRead: $result")
+    private fun Int.toAction() {
+        when (this) {
+            -99 -> {}
+            -2 -> broadcastUpdate(ACTION_CONNECT_WIFI_RESULT_TIMEOUT)
+            -1 -> broadcastUpdate(ACTION_CONNECT_WIFI_RESULT_ERROR)
+            0 -> broadcastUpdate(ACTION_CONNECT_WIFI_RESULT_SUCCESS)
+            1 -> broadcastUpdate(ACTION_CONNECT_WIFI_RESULT_CONNECTING)
+            2 -> broadcastUpdate(ACTION_CONNECT_WIFI_RESULT_FAIL)
+            3 -> broadcastUpdate(ACTION_CONNECT_WIFI_RESULT_NOT_FOUND)
+            4 -> broadcastUpdate(ACTION_CONNECT_WIFI_RESULT_PASSWORD_ERROR)
+            else -> broadcastUpdate(ACTION_CONNECT_WIFI_RESULT_ERROR)
         }
     }
 }

+ 31 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/XDIntroduceActivity.kt

@@ -0,0 +1,31 @@
+package com.luojigou.product.xiaodou
+
+import android.content.Intent
+import android.view.View
+import android.widget.Button
+import com.luojigou.product.R
+import com.luojigou.product.base.BaseActivity
+
+class XDIntroduceActivity : BaseActivity(), View.OnClickListener {
+
+    private lateinit var buttonStart: Button
+
+    override fun onCreate(savedInstanceState: android.os.Bundle?) {
+        super.onCreate(savedInstanceState)
+        setTitle("连接引导")
+
+        buttonStart = findViewById(R.id.btn_xd_start)
+        buttonStart.setOnClickListener(this)
+    }
+
+    override fun getLayoutId(): Int = R.layout.activity_xd_introduce
+
+    override fun onClick(v: View?) {
+        when (v?.id) {
+            R.id.btn_xd_start -> {
+                val intent = Intent(this, XDScanBLEActivity::class.java)
+                startActivity(intent)
+            }
+        }
+    }
+}

+ 15 - 13
xiaodou/src/main/java/com/luojigou/xiaodou/XDScanBLEActivity.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/XDScanBLEActivity.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou
+package com.luojigou.product.xiaodou
 
 import android.Manifest
 import android.bluetooth.BluetoothAdapter
@@ -10,17 +10,18 @@ import android.content.IntentFilter
 import android.content.pm.PackageManager
 import android.os.Build
 import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
 import androidx.core.app.ActivityCompat
 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
+import com.luojigou.product.R
+import com.luojigou.product.base.BaseActivity
+import com.luojigou.product.xiaodou.ble.XDScanBLEDisableFragment
+import com.luojigou.product.xiaodou.ble.XDScanBLENormalFragment
+import com.luojigou.product.xiaodou.ble.XDScanBLENotSupportFragment
+import com.luojigou.product.xiaodou.ble.XDScanBLEPermissionFragment
+import com.luojigou.product.xiaodou.ble.XDScanBLEStatus
 
 
-class XDScanBLEActivity : AppCompatActivity(), XDScanBLEStatus.Host {
+class XDScanBLEActivity : BaseActivity(), XDScanBLEStatus.Host {
     private val permissions: Array<String> by lazy {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
             arrayOf(
@@ -70,9 +71,12 @@ class XDScanBLEActivity : AppCompatActivity(), XDScanBLEStatus.Host {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_scanble)
+        setTitle("请选择要连接的设备")
     }
 
+    override fun getLayoutId(): Int = R.layout.activity_scanble
+
+
     override fun onResume() {
         super.onResume()
         registerReceiver(broadcastReceiver, IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED))
@@ -86,8 +90,7 @@ class XDScanBLEActivity : AppCompatActivity(), XDScanBLEStatus.Host {
 
     private fun checkBluetoothPermissionAndEnable() {
         val bluetoothAvailable = packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
-        val bluetoothLEAvailable =
-            packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
+        val bluetoothLEAvailable = packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
 
         if (!bluetoothAvailable || !bluetoothLEAvailable) {
             setFragment(notsupportFragment)
@@ -122,6 +125,5 @@ class XDScanBLEActivity : AppCompatActivity(), XDScanBLEStatus.Host {
         beginTransaction.commit()
     }
 
-    override fun onStatusChanged(status: XDScanBLEStatus) =
-        checkBluetoothPermissionAndEnable()
+    override fun onStatusChanged(status: XDScanBLEStatus) = checkBluetoothPermissionAndEnable()
 }

+ 18 - 11
xiaodou/src/main/java/com/luojigou/xiaodou/XDScanWifiActivity.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/XDScanWifiActivity.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou
+package com.luojigou.product.xiaodou
 
 import android.content.BroadcastReceiver
 import android.content.Context
@@ -9,14 +9,15 @@ import android.net.ConnectivityManager
 import android.net.wifi.WifiManager
 import android.os.Build
 import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
 import androidx.fragment.app.Fragment
-import com.luojigou.xiaodou.wifi.XDScanWifiDisableFragment
-import com.luojigou.xiaodou.wifi.XDScanWifiNormalFragment
-import com.luojigou.xiaodou.wifi.XDScanWifiPermissionFragment
-import com.luojigou.xiaodou.wifi.XDScanWifiStatus
-
-class XDScanWifiActivity : AppCompatActivity(), XDScanWifiStatus.Host {
+import com.luojigou.product.R
+import com.luojigou.product.base.BaseActivity
+import com.luojigou.product.xiaodou.wifi.XDScanWifiDisableFragment
+import com.luojigou.product.xiaodou.wifi.XDScanWifiNormalFragment
+import com.luojigou.product.xiaodou.wifi.XDScanWifiPermissionFragment
+import com.luojigou.product.xiaodou.wifi.XDScanWifiStatus
+
+class XDScanWifiActivity : BaseActivity(), XDScanWifiStatus.Host {
     companion object {
         fun start(context: Context) {
             context.startActivity(Intent(context, XDScanWifiActivity::class.java))
@@ -37,9 +38,15 @@ class XDScanWifiActivity : AppCompatActivity(), XDScanWifiStatus.Host {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_scanwifi)
+        setTitle("请选择要连接的Wi-Fi")
 
         wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
+    }
+
+    override fun getLayoutId(): Int = R.layout.activity_scanwifi
+
+    override fun onResume() {
+        super.onResume()
         setupReceiver()
         checkWifiPermissionAndEnable()
     }
@@ -108,8 +115,8 @@ class XDScanWifiActivity : AppCompatActivity(), XDScanWifiStatus.Host {
         return wifiManager.wifiState != WifiManager.WIFI_STATE_DISABLED
     }
 
-    override fun onDestroy() {
+    override fun onPause() {
         teardownReceiver()
-        super.onDestroy()
+        super.onPause()
     }
 }

+ 1 - 1
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDBLEConnectStatus.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDBLEConnectStatus.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.ble
+package com.luojigou.product.xiaodou.ble
 
 sealed class XDBLEConnectStatus() {
     object Waiting : XDBLEConnectStatus()

+ 1 - 1
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDBLEController.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDBLEController.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.ble
+package com.luojigou.product.xiaodou.ble
 
 import android.content.Context
 

+ 2 - 1
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDBLEUtils.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDBLEUtils.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.ble
+package com.luojigou.product.xiaodou.ble
 
 import android.util.Log
 
@@ -11,6 +11,7 @@ object XDBLEUtils {
 
     const val END_BYTE: Byte = 255.toByte()
     fun parseConnectResponse(data: ByteArray): Int {
+        if (data.size < 17) return -99
         Log.d("XDBLEUtils", "parseConnectResponse: ${data.decodeToString()}")
         return data[16] - '0'.code
     }

+ 8 - 16
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEAdapter.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEAdapter.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.ble
+package com.luojigou.product.xiaodou.ble
 
 import android.annotation.SuppressLint
 import android.view.LayoutInflater
@@ -8,14 +8,14 @@ import android.widget.ImageView
 import android.widget.TextView
 import androidx.collection.ArraySet
 import androidx.recyclerview.widget.RecyclerView
-import com.luojigou.xiaodou.R
+import com.luojigou.product.R
 
 
 @SuppressLint("MissingPermission")
 class XDScanBLEAdapter(
-    private val itemClickListener: (XDScanBLEDevice) -> Unit,
+    private val itemClickListener: (com.luojigou.product.xiaodou.ble.XDScanBLEDevice) -> Unit,
 ) : RecyclerView.Adapter<XDScanBLEAdapter.ViewHolder>() {
-    private val list: MutableSet<XDScanBLEDevice> = ArraySet()
+    private val list: MutableSet<com.luojigou.product.xiaodou.ble.XDScanBLEDevice> = ArraySet()
 
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
         val itemView: View =
@@ -29,11 +29,8 @@ class XDScanBLEAdapter(
         val item = list.elementAt(position)
 
         holder.apply {
+            img.setImageResource(R.drawable.xiaodou)
             name.text = item.name
-            bondState.text = item.bondState
-            rssi.text = item.rssi
-            address.text = item.address
-            addressType.text = item.addressType
         }
 
         holder.itemView.setOnClickListener {
@@ -42,24 +39,19 @@ class XDScanBLEAdapter(
     }
 
     @SuppressLint("NotifyDataSetChanged")
-    fun setValues(values: List<XDScanBLEDevice>) {
+    fun setValues(values: List<com.luojigou.product.xiaodou.ble.XDScanBLEDevice>) {
         list.clear()
         list.addAll(values)
         notifyDataSetChanged()
     }
 
-    fun addValue(value: XDScanBLEDevice) {
+    fun addValue(value: com.luojigou.product.xiaodou.ble.XDScanBLEDevice) {
         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 img = itemView.findViewById<ImageView>(R.id.iv_ble_icon)
         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)
     }
 }

+ 6 - 2
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEDevice.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEDevice.kt

@@ -1,5 +1,6 @@
-package com.luojigou.xiaodou.ble
+package com.luojigou.product.xiaodou.ble
 
+import android.bluetooth.BluetoothDevice
 import android.os.Parcel
 import android.os.Parcelable
 import java.util.Objects
@@ -10,6 +11,7 @@ data class XDScanBLEDevice(
     val bondState: String,
     val address: String,
     val addressType: String,
+    val device: BluetoothDevice,
 ) : Parcelable {
 
     // Parcelable Creator
@@ -23,7 +25,8 @@ data class XDScanBLEDevice(
                     source.readString()!!,
                     source.readString()!!,
                     source.readString()!!,
-                    source.readString()!!
+                    source.readString()!!,
+                    source.readParcelable(BluetoothDevice::class.java.classLoader)!!
                 )
             }
 
@@ -40,6 +43,7 @@ data class XDScanBLEDevice(
         dest.writeString(bondState)
         dest.writeString(address)
         dest.writeString(addressType)
+        dest.writeParcelable(device, flags)
     }
 
     // 实现 describeContents 方法(通常返回0)

+ 2 - 2
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEDisableFragment.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEDisableFragment.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.ble
+package com.luojigou.product.xiaodou.ble
 
 import android.annotation.SuppressLint
 import android.bluetooth.BluetoothAdapter
@@ -11,7 +11,7 @@ import android.widget.Button
 import androidx.activity.result.ActivityResultLauncher
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.fragment.app.Fragment
-import com.luojigou.xiaodou.R
+import com.luojigou.product.R
 
 @SuppressLint("MissingPermission")
 class XDScanBLEDisableFragment(private val host: XDScanBLEStatus.Host) : Fragment() {

+ 9 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEGattCallback.kt

@@ -0,0 +1,9 @@
+package com.luojigou.product.xiaodou.ble
+
+import android.annotation.SuppressLint
+import android.bluetooth.BluetoothGattCallback
+
+@SuppressLint("MissingPermission")
+class XDScanBLEGattCallback : BluetoothGattCallback() {
+
+}

+ 19 - 13
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLENormalFragment.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLENormalFragment.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.ble
+package com.luojigou.product.xiaodou.ble
 
 import android.annotation.SuppressLint
 import android.content.BroadcastReceiver
@@ -10,19 +10,20 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.widget.Button
+import android.widget.ProgressBar
 import androidx.activity.result.ActivityResultLauncher
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.core.content.ContextCompat
 import androidx.fragment.app.Fragment
 import androidx.recyclerview.widget.GridLayoutManager
 import androidx.recyclerview.widget.RecyclerView
-import com.luojigou.xiaodou.R
-import com.luojigou.xiaodou.XDScanBLEService
-import com.luojigou.xiaodou.XDScanBLEService.Companion.ACTION_SCAN_RESULT
-import com.luojigou.xiaodou.XDScanBLEService.Companion.ACTION_SCAN_RESULT_DATA
-import com.luojigou.xiaodou.XDScanBLEService.Companion.ACTION_START_SCAN
-import com.luojigou.xiaodou.XDScanBLEService.Companion.ACTION_STOP_SCAN
-import com.luojigou.xiaodou.XDScanWifiActivity
+import com.luojigou.product.R
+import com.luojigou.product.xiaodou.XDConnectService
+import com.luojigou.product.xiaodou.XDConnectService.Companion.ACTION_SCAN_RESULT
+import com.luojigou.product.xiaodou.XDConnectService.Companion.ACTION_SCAN_RESULT_DATA
+import com.luojigou.product.xiaodou.XDConnectService.Companion.ACTION_START_SCAN
+import com.luojigou.product.xiaodou.XDConnectService.Companion.ACTION_STOP_SCAN
+import com.luojigou.product.xiaodou.XDScanWifiActivity
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.MainScope
 
@@ -30,8 +31,8 @@ import kotlinx.coroutines.MainScope
 class XDScanBLENormalFragment(private val host: XDScanBLEStatus.Host) : Fragment(),
     CoroutineScope by MainScope() {
     private val adapter = XDScanBLEAdapter {
-        val intent = Intent(XDScanBLEService.ACTION_SELECT_BLE_DEVICE)
-        intent.putExtra(XDScanBLEService.ACTION_SELECT_BLE_DEVICE_DATA, it)
+        val intent = Intent(XDConnectService.ACTION_SELECT_BLE_DEVICE)
+        intent.putExtra(XDConnectService.ACTION_SELECT_BLE_DEVICE_DATA, it)
         requireActivity().sendBroadcast(intent)
         XDScanWifiActivity.start(requireContext())
     }
@@ -42,6 +43,8 @@ class XDScanBLENormalFragment(private val host: XDScanBLEStatus.Host) : Fragment
 
     private lateinit var restartScanButton: Button
 
+    private lateinit var scanProgress: ProgressBar
+
     override fun onCreateView(
         inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
     ): View? {
@@ -54,6 +57,7 @@ class XDScanBLENormalFragment(private val host: XDScanBLEStatus.Host) : Fragment
         selectWifi = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
             it.data
         }
+        scanProgress = view.findViewById(R.id.scan_progress)
 
         restartScanButton = view.findViewById<Button>(R.id.scan_again)
         restartScanButton.setOnClickListener { restartScan() }
@@ -75,10 +79,12 @@ class XDScanBLENormalFragment(private val host: XDScanBLEStatus.Host) : Fragment
             override fun onReceive(context: Context?, intent: Intent) {
                 when (intent.action) {
                     ACTION_START_SCAN -> {
+                        scanProgress.visibility = View.VISIBLE
                         restartScanButton.visibility = View.INVISIBLE
                     }
 
                     ACTION_STOP_SCAN -> {
+                        scanProgress.visibility = View.INVISIBLE
                         restartScanButton.visibility = View.VISIBLE
                     }
 
@@ -108,21 +114,21 @@ class XDScanBLENormalFragment(private val host: XDScanBLEStatus.Host) : Fragment
 
         ContextCompat.startForegroundService(
             requireContext(),
-            Intent(requireContext(), XDScanBLEService::class.java),
+            Intent(requireContext(), XDConnectService::class.java),
         )
     }
 
     private fun stopService() {
         requireContext().stopService(
             Intent(
-                requireContext(), XDScanBLEService::class.java
+                requireContext(), XDConnectService::class.java
             )
         )
     }
 
     private fun restartScan() {
         setAdapterValue(listOf())
-        val intent = Intent(XDScanBLEService.ACTION_RESTART_SCAN)
+        val intent = Intent(XDConnectService.ACTION_RESTART_SCAN)
         requireActivity().sendBroadcast(intent)
     }
 

+ 2 - 2
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLENotSupportFragment.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLENotSupportFragment.kt

@@ -1,11 +1,11 @@
-package com.luojigou.xiaodou.ble
+package com.luojigou.product.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
+import com.luojigou.product.R
 
 class XDScanBLENotSupportFragment(private val host: XDScanBLEStatus.Host) : Fragment() {
     override fun onCreateView(

+ 2 - 2
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEPermissionFragment.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEPermissionFragment.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.ble
+package com.luojigou.product.xiaodou.ble
 
 import android.Manifest
 import android.os.Build
@@ -11,7 +11,7 @@ import android.widget.Button
 import androidx.activity.result.ActivityResultLauncher
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.fragment.app.Fragment
-import com.luojigou.xiaodou.R
+import com.luojigou.product.R
 
 class XDScanBLEPermissionFragment(private val host: XDScanBLEStatus.Host) : Fragment() {
     private lateinit var requestPermission: ActivityResultLauncher<Array<String>>

+ 1 - 1
xiaodou/src/main/java/com/luojigou/xiaodou/ble/XDScanBLEStatus.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/ble/XDScanBLEStatus.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.ble
+package com.luojigou.product.xiaodou.ble
 
 sealed class XDScanBLEStatus {
     object Disabled : XDScanBLEStatus()

+ 18 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectConnectingFragment.kt

@@ -0,0 +1,18 @@
+package com.luojigou.product.xiaodou.connect
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.luojigou.product.R
+
+class XDConnectConnectingFragment : Fragment() {
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(R.layout.fragment_connect_connecting, container, false)
+    }
+}

+ 18 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectErrorFragment.kt

@@ -0,0 +1,18 @@
+package com.luojigou.product.xiaodou.connect
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.luojigou.product.R
+
+class XDConnectErrorFragment : Fragment() {
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(R.layout.fragment_connect_error, container, false)
+    }
+}

+ 18 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectFailFragment.kt

@@ -0,0 +1,18 @@
+package com.luojigou.product.xiaodou.connect
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.luojigou.product.R
+
+class XDConnectFailFragment : Fragment() {
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(R.layout.fragment_connect_fail, container, false)
+    }
+}

+ 18 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectNotFoundFragment.kt

@@ -0,0 +1,18 @@
+package com.luojigou.product.xiaodou.connect
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.luojigou.product.R
+
+class XDConnectNotFoundFragment : Fragment() {
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(R.layout.fragment_connect_not_found, container, false)
+    }
+}

+ 18 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectPasswordErrorFragment.kt

@@ -0,0 +1,18 @@
+package com.luojigou.product.xiaodou.connect
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.luojigou.product.R
+
+class XDConnectPasswordErrorFragment : Fragment() {
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(R.layout.fragment_connect_password_error, container, false)
+    }
+}

+ 18 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectSuccessFragment.kt

@@ -0,0 +1,18 @@
+package com.luojigou.product.xiaodou.connect
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.luojigou.product.R
+
+class XDConnectSuccessFragment : Fragment() {
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(R.layout.fragment_connect_success, container, false)
+    }
+}

+ 18 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/connect/XDConnectTimeoutFragment.kt

@@ -0,0 +1,18 @@
+package com.luojigou.product.xiaodou.connect
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.luojigou.product.R
+
+class XDConnectTimeoutFragment : Fragment() {
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(R.layout.fragment_connect_timeout, container, false)
+    }
+}

+ 81 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiAdapter.kt

@@ -0,0 +1,81 @@
+package com.luojigou.product.xiaodou.wifi
+
+import android.net.wifi.ScanResult
+import android.os.Build
+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
+import com.luojigou.product.R
+
+class XDScanWifiAdapter(
+    private val itemClickListener: (ScanResult) -> Unit,
+    private val addClickListener: () -> Unit,
+) : RecyclerView.Adapter<XDScanWifiAdapter.ViewHolder>() {
+    private val list: MutableList<ScanResult> = ArrayList()
+
+    override fun getItemViewType(position: Int): Int =
+        if (position == list.size) 1 else 0
+
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+        if (viewType == 1) {
+            val itemView: View = LayoutInflater.from(parent.context)
+                .inflate(R.layout.item_wifi_add, parent, false)
+            return ViewHolder(itemView)
+        } else {
+            val itemView: View = LayoutInflater.from(parent.context)
+                .inflate(R.layout.item_wifi, parent, false)
+            return ViewHolder(itemView)
+        }
+    }
+
+    override fun getItemCount(): Int =
+        list.size + 1
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        if (position == list.size) {
+            holder.itemView.setOnClickListener {
+                addClickListener.invoke()
+            }
+        } else {
+            val item = list[position]
+
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+                holder.name.text = item.wifiSsid?.toString()
+            } else {
+                holder.name.text = item.BSSID
+            }
+
+            if (item.capabilities.contains("WPA")) {
+                holder.img.setImageResource(R.drawable.ic_lock)
+            } else {
+                holder.img.setImageIcon(null)
+            }
+
+            holder.itemView.setOnClickListener {
+                itemClickListener.invoke(item)
+            }
+        }
+    }
+
+    fun addValue(result: ScanResult) {
+        val ssid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+            result.wifiSsid.toString()
+        } else {
+            result.BSSID
+        }
+
+        if (ssid != null && result.frequency in 2400..2500) {
+            list.add(result)
+            notifyItemChanged(list.size - 1)
+        }
+    }
+
+    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+        val img = itemView.findViewById<ImageView>(R.id.iv_wifi_rssi)
+        val name = itemView.findViewById<TextView>(R.id.tv_wifi_name)
+    }
+}

+ 2 - 2
xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiDisableFragment.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiDisableFragment.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.wifi
+package com.luojigou.product.xiaodou.wifi
 
 import android.content.Intent
 import android.net.wifi.WifiManager
@@ -12,7 +12,7 @@ import android.widget.Button
 import androidx.activity.result.ActivityResultLauncher
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.fragment.app.Fragment
-import com.luojigou.xiaodou.R
+import com.luojigou.product.R
 
 class XDScanWifiDisableFragment(private val host: XDScanWifiStatus.Host) : Fragment() {
     private val openWifi: ActivityResultLauncher<Intent> =

+ 1 - 1
xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiEntity.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiEntity.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.wifi
+package com.luojigou.product.xiaodou.wifi
 
 data class XDScanWifiEntity(
     val ssid:String,

+ 1 - 1
xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiInfo.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiInfo.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.wifi
+package com.luojigou.product.xiaodou.wifi
 
 import android.os.Parcel
 import android.os.Parcelable

+ 34 - 16
xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiNormalFragment.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiNormalFragment.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.wifi
+package com.luojigou.product.xiaodou.wifi
 
 import android.annotation.SuppressLint
 import android.content.BroadcastReceiver
@@ -16,18 +16,17 @@ import androidx.core.content.ContextCompat
 import androidx.fragment.app.Fragment
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
-import com.luojigou.xiaodou.R
-import com.luojigou.xiaodou.XDScanBLEService
+import com.luojigou.product.R
+import com.luojigou.product.xiaodou.XDConnectActivity
 
 @SuppressLint("MissingPermission")
 class XDScanWifiNormalFragment(private val host: XDScanWifiStatus.Host) : Fragment() {
     private lateinit var wifiScanReceiver: BroadcastReceiver
 
-    private val adapter = XDScanWifiAdapter { wifi ->
-        XDScanWifiPasswordFragment {
-            val intent = Intent(XDScanBLEService.ACTION_SELECT_WIFI_DEVICE)
-            intent.putExtra(
-                XDScanBLEService.ACTION_SELECT_WIFI_DEVICE_DATA, XDScanWifiInfo(
+    private val adapter = XDScanWifiAdapter(
+        { wifi ->
+            XDScanWifiPasswordFragment {
+                val wifi = XDScanWifiInfo(
                     ssid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                         val s = wifi.wifiSsid.toString()
                         s.substring(1, s.length - 1)
@@ -35,10 +34,29 @@ class XDScanWifiNormalFragment(private val host: XDScanWifiStatus.Host) : Fragme
                         wifi.BSSID
                     }, password = it
                 )
+
+                XDConnectActivity.startConnect(
+                    requireContext(),
+                    wifi
+                )
+            }.show(
+                requireActivity().supportFragmentManager,
+                "password"
             )
-            requireActivity().sendBroadcast(intent)
-        }.show(requireActivity().supportFragmentManager, "password")
-    }
+        },
+        {
+            XDScanWifiPasswordWithSsidFragment { ssid, pwd ->
+                XDConnectActivity.startConnect(
+                    requireContext(),
+                    XDScanWifiInfo(ssid, pwd)
+                )
+
+            }.show(
+                requireActivity().supportFragmentManager,
+                "password"
+            )
+        },
+    )
 
     override fun onCreateView(
         inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
@@ -57,9 +75,8 @@ class XDScanWifiNormalFragment(private val host: XDScanWifiStatus.Host) : Fragme
         recyclerView.adapter = adapter
     }
 
-    override fun onAttach(context: Context) {
-        super.onAttach(context)
-
+    override fun onResume() {
+        super.onResume()
         wifiScanReceiver = object : BroadcastReceiver() {
             override fun onReceive(context: Context?, intent: Intent) {
                 when (intent.action) {
@@ -87,8 +104,9 @@ class XDScanWifiNormalFragment(private val host: XDScanWifiStatus.Host) : Fragme
         host.getWifiManager().startScan()
     }
 
-    override fun onDetach() {
+    override fun onPause() {
         requireContext().unregisterReceiver(wifiScanReceiver)
-        super.onDetach()
+        host.getWifiManager().disconnect()
+        super.onPause()
     }
 }

+ 2 - 2
xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiPasswordFragment.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiPasswordFragment.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.wifi
+package com.luojigou.product.xiaodou.wifi
 
 import android.os.Bundle
 import android.view.LayoutInflater
@@ -7,7 +7,7 @@ import android.view.ViewGroup
 import android.widget.Button
 import android.widget.EditText
 import com.google.android.material.bottomsheet.BottomSheetDialogFragment
-import com.luojigou.xiaodou.R
+import com.luojigou.product.R
 
 class XDScanWifiPasswordFragment(private val onPasswordEdit: (password: String) -> Unit) :
     BottomSheetDialogFragment() {

+ 47 - 0
xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiPasswordWithSsidFragment.kt

@@ -0,0 +1,47 @@
+package com.luojigou.product.xiaodou.wifi
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.inputmethod.InputMethodManager
+import android.widget.Button
+import android.widget.EditText
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import com.luojigou.product.R
+
+class XDScanWifiPasswordWithSsidFragment(private val onPasswordEdit: (ssid: String, password: String) -> Unit) :
+    BottomSheetDialogFragment() {
+
+    private lateinit var ssid: EditText
+    private lateinit var pwd: EditText
+    override fun onCreateView(
+        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+    ): View {
+        return inflater.inflate(R.layout.fragment_scanwifi_password_with_ssid, container, false)
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        ssid = view.findViewById<EditText>(R.id.et_ssid)
+        pwd = view.findViewById<EditText>(R.id.et_pwd)
+        val button = view.findViewById<Button>(R.id.btn_pwd)
+
+        button.setOnClickListener {
+            val ssidText = ssid.getText()
+            val pwdText = pwd.getText()
+            onPasswordEdit.invoke(ssidText.toString(), pwdText.toString())
+            dismiss()
+        }
+    }
+
+    override fun onResume() {
+        super.onResume()
+
+        ssid.requestFocus()
+        val ims = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+        ims.showSoftInput(ssid, InputMethodManager.SHOW_IMPLICIT)
+    }
+}

+ 2 - 2
xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiPermissionFragment.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiPermissionFragment.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.wifi
+package com.luojigou.product.xiaodou.wifi
 
 import android.os.Build
 import android.os.Bundle
@@ -10,7 +10,7 @@ import android.widget.Button
 import androidx.activity.result.ActivityResultLauncher
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.fragment.app.Fragment
-import com.luojigou.xiaodou.R
+import com.luojigou.product.R
 
 class XDScanWifiPermissionFragment(private val host: XDScanWifiStatus.Host) : Fragment() {
     private val requestPermission: ActivityResultLauncher<Array<String>> =

+ 1 - 1
xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiStatus.kt → xiaodou/src/main/java/com/luojigou/product/xiaodou/wifi/XDScanWifiStatus.kt

@@ -1,4 +1,4 @@
-package com.luojigou.xiaodou.wifi
+package com.luojigou.product.xiaodou.wifi
 
 import android.net.wifi.WifiManager
 

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

@@ -1,15 +0,0 @@
-package com.luojigou.xiaodou
-
-import android.content.Context
-import android.net.wifi.WifiManager
-import android.os.Bundle
-import android.util.Log
-import androidx.appcompat.app.AppCompatActivity
-
-class XDBindFailureActivity : AppCompatActivity() {
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_bind_failure)
-  }
-}

+ 0 - 11
xiaodou/src/main/java/com/luojigou/xiaodou/XDBindSuccessActivity.kt

@@ -1,11 +0,0 @@
-package com.luojigou.xiaodou
-
-import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
-
-class XDBindSuccessActivity : AppCompatActivity() {
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_bind_success)
-    }
-}

+ 0 - 4
xiaodou/src/main/java/com/luojigou/xiaodou/XDConnectActivity.kt

@@ -1,4 +0,0 @@
-package com.luojigou.xiaodou
-
-class XDConnectActivity {
-}

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

@@ -1,13 +0,0 @@
-package com.luojigou.xiaodou.ble
-
-import android.annotation.SuppressLint
-import android.bluetooth.BluetoothGatt
-import android.bluetooth.BluetoothGattCallback
-import android.bluetooth.BluetoothProfile
-import android.util.Log
-import com.luojigou.xiaodou.XDScanBLEService
-
-@SuppressLint("MissingPermission")
-class XDScanBLEGattCallback : BluetoothGattCallback() {
-
-}

+ 0 - 58
xiaodou/src/main/java/com/luojigou/xiaodou/wifi/XDScanWifiAdapter.kt

@@ -1,58 +0,0 @@
-package com.luojigou.xiaodou.wifi
-
-import android.net.wifi.ScanResult
-import android.os.Build
-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
-import com.luojigou.xiaodou.R
-
-class XDScanWifiAdapter(
-    private val itemClickListener: (ScanResult) -> Unit,
-) : 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_wifi, parent, false)
-        return ViewHolder(itemView)
-    }
-
-    override fun getItemCount(): Int =
-        list.size
-
-    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
-        val item = list[position]
-
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
-            holder.name.text = item.wifiSsid?.toString()
-        } else {
-            holder.name.text = item.BSSID
-        }
-
-        holder.itemView.setOnClickListener {
-            itemClickListener.invoke(item)
-        }
-    }
-
-    fun addValue(result: ScanResult) {
-        val ssid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
-            result.wifiSsid.toString()
-        } else {
-            result.BSSID
-        }
-
-        if (ssid != null && result.frequency in 2400..2500) {
-            list.add(result)
-            notifyItemChanged(list.size - 1)
-        }
-    }
-
-    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
-        val img = itemView.findViewById<ImageView>(R.id.iv_wifi_rssi)
-        val name = itemView.findViewById<TextView>(R.id.tv_wifi_name)
-    }
-}

+ 24 - 0
xiaodou/src/main/res-xiaodou/layout/activity_xd_introduce.xml

@@ -0,0 +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">
+
+    <TextView
+        android:id="@+id/tv_xd_introduce"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="这里是连接指导说明"
+        app:layout_constraintBottom_toTopOf="@id/btn_xd_start"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <Button
+        android:id="@+id/btn_xd_start"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="16dp"
+        android:text="确认并进入下一步"
+        app:layout_constraintBottom_toBottomOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 27 - 0
xiaodou/src/main/res/drawable/ic_lock.xml

@@ -0,0 +1,27 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M5,13a2,2 0,0 1,2 -2h10a2,2 0,0 1,2 2v6a2,2 0,0 1,-2 2h-10a2,2 0,0 1,-2 -2v-6z"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="currentColor"
+      android:strokeLineCap="round"/>
+  <path
+      android:pathData="M11,16a1,1 0,1 0,2 0a1,1 0,0 0,-2 0"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="currentColor"
+      android:strokeLineCap="round"/>
+  <path
+      android:pathData="M8,11v-4a4,4 0,1 1,8 0v4"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="currentColor"
+      android:strokeLineCap="round"/>
+</vector>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 9 - 0
xiaodou/src/main/res/drawable/xiaodou.xml


+ 0 - 6
xiaodou/src/main/res/layout/activity_bind_failure.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-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.constraintlayout.widget.ConstraintLayout>

+ 0 - 6
xiaodou/src/main/res/layout/activity_bind_success.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-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.constraintlayout.widget.ConstraintLayout>

+ 12 - 0
xiaodou/src/main/res/layout/activity_connect.xml

@@ -0,0 +1,12 @@
+<?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">
+
+    <androidx.fragment.app.FragmentContainerView
+        android:id="@+id/fragment_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 11 - 0
xiaodou/src/main/res/layout/activity_product_select.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-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/rv_product_list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 29 - 0
xiaodou/src/main/res/layout/fragment_connect_connecting.xml

@@ -0,0 +1,29 @@
+<?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">
+
+    <ProgressBar
+        android:id="@+id/pb_connecting"
+        android:layout_width="320dp"
+        android:layout_height="400dp"
+        android:paddingLeft="140dp"
+        android:paddingTop="180dp"
+        android:paddingRight="140dp"
+        android:paddingBottom="180dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_connecting"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="连接中"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/pb_connecting" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 29 - 0
xiaodou/src/main/res/layout/fragment_connect_error.xml

@@ -0,0 +1,29 @@
+<?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">
+
+    <ImageView
+        android:id="@+id/pb_connecting"
+        android:layout_width="320dp"
+        android:layout_height="400dp"
+        android:paddingLeft="140dp"
+        android:paddingTop="180dp"
+        android:paddingRight="140dp"
+        android:paddingBottom="180dp"
+        android:src="@android:drawable/stat_notify_error"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_connecting"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="连接出错"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/pb_connecting" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 31 - 0
xiaodou/src/main/res/layout/fragment_connect_fail.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <ImageView
+        android:id="@+id/pb_connecting"
+        android:layout_width="320dp"
+        android:layout_height="400dp"
+        android:paddingLeft="140dp"
+        android:paddingTop="180dp"
+        android:paddingRight="140dp"
+        android:paddingBottom="180dp"
+        android:src="@android:drawable/stat_notify_error"
+        android:background="@android:color/holo_red_dark"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_connecting"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="连接失败"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/pb_connecting" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 31 - 0
xiaodou/src/main/res/layout/fragment_connect_not_found.xml

@@ -0,0 +1,31 @@
+<?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">
+
+
+    <ImageView
+        android:id="@+id/pb_connecting"
+        android:layout_width="320dp"
+        android:layout_height="400dp"
+        android:paddingLeft="140dp"
+        android:paddingTop="180dp"
+        android:paddingRight="140dp"
+        android:paddingBottom="180dp"
+        android:background="@android:color/darker_gray"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_connecting"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="连接的WIFI不存在"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/pb_connecting" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 29 - 0
xiaodou/src/main/res/layout/fragment_connect_password_error.xml

@@ -0,0 +1,29 @@
+<?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">
+
+    <ImageView
+        android:id="@+id/pb_connecting"
+        android:layout_width="320dp"
+        android:layout_height="400dp"
+        android:paddingLeft="140dp"
+        android:paddingTop="180dp"
+        android:paddingRight="140dp"
+        android:paddingBottom="180dp"
+        android:background="@android:color/holo_red_light"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_connecting"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="WIFI密码错误"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/pb_connecting" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 29 - 0
xiaodou/src/main/res/layout/fragment_connect_success.xml

@@ -0,0 +1,29 @@
+<?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">
+
+    <ImageView
+        android:id="@+id/pb_connecting"
+        android:layout_width="320dp"
+        android:layout_height="400dp"
+        android:paddingLeft="140dp"
+        android:paddingTop="180dp"
+        android:paddingRight="140dp"
+        android:paddingBottom="180dp"
+        android:background="@android:color/holo_green_light"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_connecting"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="配网成功"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/pb_connecting" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 29 - 0
xiaodou/src/main/res/layout/fragment_connect_timeout.xml

@@ -0,0 +1,29 @@
+<?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">
+
+    <ImageView
+        android:id="@+id/pb_connecting"
+        android:layout_width="320dp"
+        android:layout_height="400dp"
+        android:paddingLeft="140dp"
+        android:paddingTop="180dp"
+        android:paddingRight="140dp"
+        android:paddingBottom="180dp"
+        android:background="@android:color/holo_blue_light"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tv_connecting"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="配网超时"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/pb_connecting" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 8 - 0
xiaodou/src/main/res/layout/fragment_scanble_normal.xml

@@ -9,6 +9,14 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
+    <ProgressBar
+        android:id="@+id/scan_progress"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
 
     <Button
         android:id="@+id/scan_again"

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

@@ -15,5 +15,5 @@
         android:id="@+id/btn_pwd"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="这是一个底部滑出对话框" />
+        android:text="确定" />
 </LinearLayout>

+ 26 - 0
xiaodou/src/main/res/layout/fragment_scanwifi_password_with_ssid.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:padding="16dp">
+
+    <EditText
+        android:id="@+id/et_ssid"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:focusable="auto"
+        android:hint="请在此输入wifi名称" />
+
+    <EditText
+        android:id="@+id/et_pwd"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:hint="请在此输入wifi密码" />
+
+    <Button
+        android:id="@+id/btn_pwd"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="确定" />
+</LinearLayout>

+ 4 - 37
xiaodou/src/main/res/layout/item_ble.xml

@@ -5,49 +5,16 @@
     android:orientation="vertical">
 
     <ImageView
-        android:id="@+id/iv_ble"
+        android:id="@+id/iv_ble_icon"
         android:layout_width="match_parent"
-        android:layout_height="100dp" />
-
-    <TextView
-        android:id="@+id/tv_ble_id"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="start"
-        android:text="" />
+        android:layout_margin="16dp"
+        android:layout_height="160dp" />
 
     <TextView
         android:id="@+id/tv_ble_name"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        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:layout_gravity="center_horizontal"
         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>

+ 20 - 0
xiaodou/src/main/res/layout/item_product.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <ImageView
+        android:id="@+id/iv_product_img"
+        android:layout_width="match_parent"
+        android:layout_height="160dp"
+        android:layout_margin="16dp" />
+
+    <TextView
+        android:id="@+id/tv_product_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:text="" />
+
+</LinearLayout>

+ 22 - 1
xiaodou/src/main/res/layout/item_wifi_add.xml

@@ -1,6 +1,27 @@
 <?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"
+        android:src="@android:drawable/ic_menu_add"
+        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"
+        android:gravity="center_vertical"
+        android:text="手动添加一个WIFI"
+        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>

+ 5 - 1
xiaodou/src/main/res/values/themes.xml

@@ -1,5 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <style name="XDTheme" parent="Theme.Material3.Light.NoActionBar">
+
+    <style name="XDTheme" parent="Theme.Material3.Light">
+        <item name="statusBarBackground">@android:color/transparent</item>
+        <item name="android:statusBarColor">@android:color/transparent</item>
+        <item name="android:windowLightStatusBar">true</item>
     </style>
 </resources>

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác