diff --git a/.idea/deviceManager.xml b/.idea/deviceManager.xml
new file mode 100644
index 0000000..91f9558
--- /dev/null
+++ b/.idea/deviceManager.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.kotlin/errors/errors-1778028479135.log b/.kotlin/errors/errors-1778028479135.log
new file mode 100644
index 0000000..e99c6ac
--- /dev/null
+++ b/.kotlin/errors/errors-1778028479135.log
@@ -0,0 +1,48 @@
+kotlin version: 2.2.10
+error message: java.nio.file.AccessDeniedException: C:\Users\Administrator\AppData\Local\kotlin\daemon\kotlin-daemon-client-tsmarker2497125691510638864.tmp
+
+error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
+java.lang.RuntimeException: Could not connect to Kotlin compile daemon
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
+ at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:74)
+ at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:64)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:61)
+ at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:102)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:61)
+ at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
+ at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
+ at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:58)
+ at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:176)
+ at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
+ at org.gradle.internal.Factories$1.create(Factories.java:30)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withLocksAcquired$0(DefaultWorkerLeaseService.java:269)
+ at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.withLocksAcquired(DefaultWorkerLeaseService.java:267)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:259)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
+ at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
+ at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
+ at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
+ at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
+ at java.base/java.lang.Thread.run(Thread.java:1583)
+
+
diff --git a/.kotlin/errors/errors-1778028479894.log b/.kotlin/errors/errors-1778028479894.log
new file mode 100644
index 0000000..d644ecc
--- /dev/null
+++ b/.kotlin/errors/errors-1778028479894.log
@@ -0,0 +1,48 @@
+kotlin version: 2.2.10
+error message: java.nio.file.AccessDeniedException: C:\Users\Administrator\AppData\Local\kotlin\daemon\kotlin-daemon-client-tsmarker13401715878096134783.tmp
+
+error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
+java.lang.RuntimeException: Could not connect to Kotlin compile daemon
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
+ at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:74)
+ at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:64)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:61)
+ at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:102)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:61)
+ at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
+ at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
+ at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:58)
+ at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:176)
+ at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
+ at org.gradle.internal.Factories$1.create(Factories.java:30)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withLocksAcquired$0(DefaultWorkerLeaseService.java:269)
+ at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.withLocksAcquired(DefaultWorkerLeaseService.java:267)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:259)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
+ at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
+ at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
+ at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
+ at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
+ at java.base/java.lang.Thread.run(Thread.java:1583)
+
+
diff --git a/.kotlin/errors/errors-1778028480507.log b/.kotlin/errors/errors-1778028480507.log
new file mode 100644
index 0000000..bccd24f
--- /dev/null
+++ b/.kotlin/errors/errors-1778028480507.log
@@ -0,0 +1,48 @@
+kotlin version: 2.2.10
+error message: java.nio.file.AccessDeniedException: C:\Users\Administrator\AppData\Local\kotlin\daemon\kotlin-daemon-client-tsmarker15696211365864685003.tmp
+
+error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
+java.lang.RuntimeException: Could not connect to Kotlin compile daemon
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
+ at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:74)
+ at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:64)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:61)
+ at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:102)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:61)
+ at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
+ at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
+ at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:58)
+ at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:176)
+ at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
+ at org.gradle.internal.Factories$1.create(Factories.java:30)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withLocksAcquired$0(DefaultWorkerLeaseService.java:269)
+ at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.withLocksAcquired(DefaultWorkerLeaseService.java:267)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:259)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
+ at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
+ at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
+ at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
+ at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
+ at java.base/java.lang.Thread.run(Thread.java:1583)
+
+
diff --git a/.kotlin/errors/errors-1778033946759.log b/.kotlin/errors/errors-1778033946759.log
new file mode 100644
index 0000000..2a87f3f
--- /dev/null
+++ b/.kotlin/errors/errors-1778033946759.log
@@ -0,0 +1,48 @@
+kotlin version: 2.2.10
+error message: java.nio.file.AccessDeniedException: C:\Users\Administrator\AppData\Local\kotlin\daemon\kotlin-daemon-client-tsmarker8173295206901294308.tmp
+
+error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
+java.lang.RuntimeException: Could not connect to Kotlin compile daemon
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
+ at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
+ at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:74)
+ at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:64)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:61)
+ at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:102)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:61)
+ at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
+ at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
+ at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
+ at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
+ at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:58)
+ at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:176)
+ at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
+ at org.gradle.internal.Factories$1.create(Factories.java:30)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withLocksAcquired$0(DefaultWorkerLeaseService.java:269)
+ at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.withLocksAcquired(DefaultWorkerLeaseService.java:267)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:259)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
+ at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
+ at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
+ at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
+ at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
+ at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
+ at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
+ at java.base/java.lang.Thread.run(Thread.java:1583)
+
+
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index fa6f916..751c58f 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -74,4 +74,6 @@ dependencies {
implementation("com.github.bumptech.glide:glide:4.15.1")
//Glide 依赖
implementation("com.github.bumptech.glide:glide:4.16.0")
+ // ZXing 二维码扫描库
+ implementation("com.google.zxing:core:3.5.2")
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ff1d529..a0a16f1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -23,6 +23,12 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.DefenseApplication">
+
+
diff --git a/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt b/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt
index c3a001c..f7b7287 100644
--- a/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt
+++ b/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt
@@ -75,7 +75,7 @@ class HomeMenuFragment : Fragment() {
startActivity(intent)
}
binding.addFamily.setOnClickListener {
- val intent = Intent(requireContext(), AddFamilyActivity::class.java)
+ val intent = Intent(requireContext(), ScanActivity::class.java)
startActivity(intent)
}
}
diff --git a/app/src/main/java/com/example/defenseapplication/home/ScanActivity.kt b/app/src/main/java/com/example/defenseapplication/home/ScanActivity.kt
new file mode 100644
index 0000000..f505c09
--- /dev/null
+++ b/app/src/main/java/com/example/defenseapplication/home/ScanActivity.kt
@@ -0,0 +1,291 @@
+package com.example.defenseapplication.home
+
+import android.Manifest
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.ImageFormat
+import android.graphics.Matrix
+import android.graphics.RectF
+import android.graphics.SurfaceTexture
+import android.hardware.Camera
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.provider.MediaStore
+import android.view.SurfaceHolder
+import android.view.SurfaceView
+import android.view.View
+import android.view.animation.Animation
+import android.view.animation.LinearInterpolator
+import android.view.animation.TranslateAnimation
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+import com.example.defenseapplication.R
+import com.example.defenseapplication.databinding.ScanActivityBinding
+import com.google.zxing.*
+import com.google.zxing.common.HybridBinarizer
+import java.util.*
+
+class ScanActivity : AppCompatActivity(), SurfaceHolder.Callback {
+
+ private lateinit var binding: ScanActivityBinding
+ private var camera: Camera? = null
+ private var isFlashlightOn = false
+ private var scanHandler: Handler? = null
+ private var scanRunnable: Runnable? = null
+ private val REQUEST_CODE_CAMERA = 100
+ private val REQUEST_CODE_ALBUM = 101
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ScanActivityBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ initView()
+ initListener()
+ startScanLineAnimation()
+ }
+
+ private fun initView() {
+ binding.surfaceView.holder.addCallback(this)
+ }
+
+ private fun initListener() {
+ binding.btnBack.setOnClickListener {
+ finish()
+ }
+
+ binding.llAlbum.setOnClickListener {
+ openAlbum()
+ }
+
+ binding.llFlashlight.setOnClickListener {
+ toggleFlashlight()
+ }
+ }
+
+ private fun startScanLineAnimation() {
+ val animation = TranslateAnimation(
+ Animation.RELATIVE_TO_PARENT, 0f,
+ Animation.RELATIVE_TO_PARENT, 0f,
+ Animation.RELATIVE_TO_PARENT, 0f,
+ Animation.RELATIVE_TO_PARENT, 1f
+ )
+ animation.duration = 2000
+ animation.repeatCount = Animation.INFINITE
+ animation.interpolator = LinearInterpolator()
+ binding.scanLine.startAnimation(animation)
+ }
+
+ private fun openAlbum() {
+ val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
+ startActivityForResult(intent, REQUEST_CODE_ALBUM)
+ }
+
+ private fun toggleFlashlight() {
+ if (camera == null) {
+ Toast.makeText(this, "相机未准备好", Toast.LENGTH_SHORT).show()
+ return
+ }
+
+ isFlashlightOn = !isFlashlightOn
+ val params = camera?.parameters
+
+ if (isFlashlightOn) {
+ params?.flashMode = Camera.Parameters.FLASH_MODE_TORCH
+ binding.ivFlashlight.setColorFilter(ContextCompat.getColor(this, R.color.green))
+ } else {
+ params?.flashMode = Camera.Parameters.FLASH_MODE_OFF
+ binding.ivFlashlight.clearColorFilter()
+ }
+
+ camera?.parameters = params
+ }
+
+ private fun checkCameraPermission(): Boolean {
+ return ContextCompat.checkSelfPermission(
+ this,
+ Manifest.permission.CAMERA
+ ) == PackageManager.PERMISSION_GRANTED
+ }
+
+ private fun requestCameraPermission() {
+ ActivityCompat.requestPermissions(
+ this,
+ arrayOf(Manifest.permission.CAMERA),
+ REQUEST_CODE_CAMERA
+ )
+ }
+
+ private fun openCamera() {
+ if (!checkCameraPermission()) {
+ requestCameraPermission()
+ return
+ }
+
+ try {
+ camera = Camera.open()
+ camera?.setDisplayOrientation(90)
+
+ val params = camera?.parameters
+ params?.previewFormat = ImageFormat.NV21
+
+ val sizes = params?.supportedPreviewSizes
+ val optimalSize = getOptimalPreviewSize(sizes, binding.surfaceView.width, binding.surfaceView.height)
+ if (optimalSize != null) {
+ params?.setPreviewSize(optimalSize.width, optimalSize.height)
+ }
+
+ camera?.parameters = params
+ camera?.setPreviewDisplay(binding.surfaceView.holder)
+ camera?.startPreview()
+
+ startScanDecode()
+ } catch (e: Exception) {
+ Toast.makeText(this, "无法打开相机", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ private fun getOptimalPreviewSize(sizes: List?, w: Int, h: Int): Camera.Size? {
+ if (sizes == null) return null
+
+ var optimalSize: Camera.Size? = null
+ val targetRatio = h.toDouble() / w.toDouble()
+
+ for (size in sizes) {
+ val ratio = size.width.toDouble() / size.height.toDouble()
+ if (Math.abs(ratio - targetRatio) < 0.01) {
+ optimalSize = size
+ break
+ }
+ }
+
+ if (optimalSize == null) {
+ var minDiff = Int.MAX_VALUE
+ for (size in sizes) {
+ val diff = Math.abs(size.width - w) + Math.abs(size.height - h)
+ if (diff < minDiff) {
+ optimalSize = size
+ minDiff = diff
+ }
+ }
+ }
+
+ return optimalSize
+ }
+
+ private fun startScanDecode() {
+ scanHandler = Handler(Looper.getMainLooper())
+ scanRunnable = object : Runnable {
+ override fun run() {
+ decodeQRCode()
+ scanHandler?.postDelayed(this, 100)
+ }
+ }
+ scanHandler?.post(scanRunnable!!)
+ }
+
+ private fun decodeQRCode() {
+ if (camera == null) return
+
+ try {
+ val parameters = camera?.parameters
+ val size = parameters?.previewSize
+ if (size == null) return
+
+ val data = ByteArray(size.width * size.height * 3 / 2)
+ camera?.setOneShotPreviewCallback { bytes, _ ->
+ val source = PlanarYUVLuminanceSource(
+ bytes, size.width, size.height, 0, 0,
+ size.width, size.height, false
+ )
+ val binarizer = HybridBinarizer(source)
+ val bitmap = BinaryBitmap(binarizer)
+
+ val reader = MultiFormatReader()
+ val hints = Hashtable()
+ hints[DecodeHintType.CHARACTER_SET] = "UTF-8"
+ reader.setHints(hints)
+
+ try {
+ val result = reader.decode(bitmap)
+ handleScanResult(result.text)
+ } catch (e: Exception) {
+ }
+ }
+ } catch (e: Exception) {
+ }
+ }
+
+ private fun handleScanResult(result: String) {
+ stopScanDecode()
+ camera?.stopPreview()
+
+ Toast.makeText(this, "扫描结果: $result", Toast.LENGTH_SHORT).show()
+
+ val intent = Intent(this, AddFamilyActivity::class.java)
+ intent.putExtra("device_code", result)
+ startActivity(intent)
+ finish()
+ }
+
+ private fun stopScanDecode() {
+ scanRunnable?.let { scanHandler?.removeCallbacks(it) }
+ scanHandler = null
+ scanRunnable = null
+ }
+
+ override fun surfaceCreated(holder: SurfaceHolder) {
+ openCamera()
+ }
+
+ override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
+ if (camera != null) {
+ camera?.stopPreview()
+ try {
+ camera?.setPreviewDisplay(holder)
+ camera?.startPreview()
+ } catch (e: Exception) {
+ }
+ }
+ }
+
+ override fun surfaceDestroyed(holder: SurfaceHolder) {
+ stopScanDecode()
+ camera?.stopPreview()
+ camera?.release()
+ camera = null
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ if (requestCode == REQUEST_CODE_CAMERA) {
+ if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ openCamera()
+ } else {
+ Toast.makeText(this, "需要相机权限", Toast.LENGTH_SHORT).show()
+ finish()
+ }
+ }
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (requestCode == REQUEST_CODE_ALBUM && resultCode == RESULT_OK && data != null) {
+ val uri = data.data
+ uri?.let {
+ Toast.makeText(this, "已选择图片", Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ stopScanDecode()
+ camera?.stopPreview()
+ camera?.release()
+ camera = null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/defenseapplication/liveVideo/LiveVideoActivity.kt b/app/src/main/java/com/example/defenseapplication/liveVideo/LiveVideoActivity.kt
new file mode 100644
index 0000000..958b1b7
--- /dev/null
+++ b/app/src/main/java/com/example/defenseapplication/liveVideo/LiveVideoActivity.kt
@@ -0,0 +1,133 @@
+package com.example.defenseapplication.liveVideo
+
+import android.content.Context
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.view.View
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import com.example.defenseapplication.databinding.LiveVideoActivityBinding
+
+class LiveVideoActivity : AppCompatActivity() {
+ private lateinit var binding: LiveVideoActivityBinding
+
+ private var isVoiceEnabled = false
+ private var isLightOn = false
+ private var isRecording = false
+ private var recordTime = 0
+ private var recordHandler: Handler? = null
+ private var recordRunnable: Runnable? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = LiveVideoActivityBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ initListener()
+ }
+
+ private fun initListener() {
+ // 返回按钮
+ binding.btnBack.setOnClickListener {
+ finish()
+ }
+
+ // 菜单按钮
+ binding.ivMenu.setOnClickListener {
+ Toast.makeText(this, "菜单", Toast.LENGTH_SHORT).show()
+ }
+
+ // 全屏按钮
+ binding.ivFullscreen.setOnClickListener {
+ Toast.makeText(this, "全屏", Toast.LENGTH_SHORT).show()
+ }
+
+ // 语音按钮
+ binding.llVoice.setOnClickListener {
+ toggleVoice()
+ }
+
+ // 灯光按钮
+ binding.llLight.setOnClickListener {
+ toggleLight()
+ }
+
+ // 录像按钮
+ binding.llRecord.setOnClickListener {
+ toggleRecording()
+ }
+
+ // 告警日志区域
+ binding.llAlarmLog.setOnClickListener {
+ Toast.makeText(this, "查看告警日志", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ private fun toggleVoice() {
+ isVoiceEnabled = !isVoiceEnabled
+
+ if (isVoiceEnabled) {
+ binding.vVoiceActive.visibility = View.VISIBLE
+ binding.ivVoice.setColorFilter(resources.getColor(com.example.defenseapplication.R.color.green))
+ Toast.makeText(this, "语音已开启", Toast.LENGTH_SHORT).show()
+ } else {
+ binding.vVoiceActive.visibility = View.INVISIBLE
+ binding.ivVoice.clearColorFilter()
+ Toast.makeText(this, "语音已关闭", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ private fun toggleLight() {
+ isLightOn = !isLightOn
+
+ if (isLightOn) {
+ binding.ivLight.setImageResource(com.example.defenseapplication.R.drawable.light_on)
+ binding.ivLight.setColorFilter(resources.getColor(com.example.defenseapplication.R.color.green))
+ Toast.makeText(this, "灯光已开启", Toast.LENGTH_SHORT).show()
+ } else {
+ binding.ivLight.setImageResource(com.example.defenseapplication.R.drawable.low_light)
+ binding.ivLight.clearColorFilter()
+ Toast.makeText(this, "灯光已关闭", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ private fun toggleRecording() {
+ isRecording = !isRecording
+
+ if (isRecording) {
+ recordTime = 0
+ binding.tvRecordTime.text = "00"
+ startRecordTimer()
+ binding.ivRecord.setColorFilter(resources.getColor(com.example.defenseapplication.R.color.red))
+ Toast.makeText(this, "开始录像", Toast.LENGTH_SHORT).show()
+ } else {
+ stopRecordTimer()
+ binding.ivRecord.clearColorFilter()
+ Toast.makeText(this, "停止录像,共录制 ${recordTime} 秒", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ private fun startRecordTimer() {
+ recordHandler = Handler(Looper.getMainLooper())
+ recordRunnable = object : Runnable {
+ override fun run() {
+ recordTime++
+ binding.tvRecordTime.text = String.format("%02d", recordTime)
+ recordHandler?.postDelayed(this, 1000)
+ }
+ }
+ recordHandler?.post(recordRunnable!!)
+ }
+
+ private fun stopRecordTimer() {
+ recordRunnable?.let { recordHandler?.removeCallbacks(it) }
+ recordHandler = null
+ recordRunnable = null
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ stopRecordTimer()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/album.png b/app/src/main/res/drawable/album.png
new file mode 100644
index 0000000..303b58c
Binary files /dev/null and b/app/src/main/res/drawable/album.png differ
diff --git a/app/src/main/res/drawable/back2.png b/app/src/main/res/drawable/back2.png
new file mode 100644
index 0000000..6e4c014
Binary files /dev/null and b/app/src/main/res/drawable/back2.png differ
diff --git a/app/src/main/res/drawable/bg_button_circle.xml b/app/src/main/res/drawable/bg_button_circle.xml
new file mode 100644
index 0000000..c6e4c37
--- /dev/null
+++ b/app/src/main/res/drawable/bg_button_circle.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_scan_frame.xml b/app/src/main/res/drawable/bg_scan_frame.xml
new file mode 100644
index 0000000..f7b2f09
--- /dev/null
+++ b/app/src/main/res/drawable/bg_scan_frame.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/copy.png b/app/src/main/res/drawable/copy.png
new file mode 100644
index 0000000..b91a1e4
Binary files /dev/null and b/app/src/main/res/drawable/copy.png differ
diff --git a/app/src/main/res/drawable/corner_bottom_left.xml b/app/src/main/res/drawable/corner_bottom_left.xml
new file mode 100644
index 0000000..768e638
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bottom_left.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bottom_right.xml b/app/src/main/res/drawable/corner_bottom_right.xml
new file mode 100644
index 0000000..662202c
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bottom_right.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_top_left.xml b/app/src/main/res/drawable/corner_top_left.xml
new file mode 100644
index 0000000..6bff040
--- /dev/null
+++ b/app/src/main/res/drawable/corner_top_left.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_top_right.xml b/app/src/main/res/drawable/corner_top_right.xml
new file mode 100644
index 0000000..698b660
--- /dev/null
+++ b/app/src/main/res/drawable/corner_top_right.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/flashlight.png b/app/src/main/res/drawable/flashlight.png
new file mode 100644
index 0000000..530b282
Binary files /dev/null and b/app/src/main/res/drawable/flashlight.png differ
diff --git a/app/src/main/res/drawable/light_on.png b/app/src/main/res/drawable/light_on.png
new file mode 100644
index 0000000..f344109
Binary files /dev/null and b/app/src/main/res/drawable/light_on.png differ
diff --git a/app/src/main/res/drawable/settings.png b/app/src/main/res/drawable/settings.png
new file mode 100644
index 0000000..77a6f3b
Binary files /dev/null and b/app/src/main/res/drawable/settings.png differ
diff --git a/app/src/main/res/drawable/voice.png b/app/src/main/res/drawable/voice.png
new file mode 100644
index 0000000..b7d1394
Binary files /dev/null and b/app/src/main/res/drawable/voice.png differ
diff --git a/app/src/main/res/layout/live_video_activity.xml b/app/src/main/res/layout/live_video_activity.xml
new file mode 100644
index 0000000..60ab653
--- /dev/null
+++ b/app/src/main/res/layout/live_video_activity.xml
@@ -0,0 +1,342 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/scan_activity.xml b/app/src/main/res/layout/scan_activity.xml
new file mode 100644
index 0000000..6317961
--- /dev/null
+++ b/app/src/main/res/layout/scan_activity.xml
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file