Compare commits
66 Commits
native1
...
fafefa3c38
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fafefa3c38 | ||
|
|
a05cebae3f | ||
|
|
638233279f | ||
|
|
8b413c5a0c | ||
|
|
d79f43e2c9 | ||
|
|
8e237bd24a | ||
|
|
9f31f12463 | ||
|
|
55cf7196a6 | ||
|
|
fb99e7ecf4 | ||
| f154f30e2d | |||
| 7114e36165 | |||
| 195fb73620 | |||
| 655279a8a1 | |||
| 46385d5358 | |||
| ab0dd2fbf6 | |||
| a9a69ca31b | |||
| 1d54d6aa2a | |||
| 200086301a | |||
| 0d0838d0e1 | |||
| a132cdfd27 | |||
| 96c8cca033 | |||
| 07f634ae05 | |||
| 4819dbce86 | |||
| 6942abca3b | |||
| 02fc928f20 | |||
| b67de551ba | |||
| e28e167085 | |||
| 8cd802a826 | |||
| 7e14dd379a | |||
| 4a584fa7d7 | |||
| a32c165424 | |||
| 9177c00a3c | |||
| e937ce207c | |||
| 4462ba5ba2 | |||
| 0672d762c9 | |||
| efbba44250 | |||
| ef4dfb0307 | |||
| 086f1226a1 | |||
| 5cf30411c1 | |||
| 76e4949dd7 | |||
| 4a16010bd6 | |||
| b55d9a4b38 | |||
| 6a1cfaeda9 | |||
| f57975ef1e | |||
| 548d501a44 | |||
| a997190480 | |||
| 631f9831c3 | |||
| b2c3ed9015 | |||
| 6bd31327db | |||
| 7e362038b3 | |||
| d30c025874 | |||
| 78d2d2cd79 | |||
| 9eb47345fe | |||
| 57188d27cc | |||
| e40403f7db | |||
| 09fdb75644 | |||
| 0f07736d1e | |||
| e7331f64f4 | |||
| 98e7d57c7d | |||
| 3c8ac29398 | |||
| 5f945fe6e3 | |||
| 11ab4e244d | |||
| 5cafd2ac1d | |||
| c2b947c630 | |||
| d60322cbc2 | |||
| 88c791a520 |
11
.idea/deploymentTargetSelector.xml
generated
11
.idea/deploymentTargetSelector.xml
generated
@@ -3,6 +3,17 @@
|
||||
<component name="deploymentTargetSelector">
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2026-06-22T08:46:41.014465400Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=80bece4" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
<SelectionState runConfigName="AlarmLogActivity">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2026-05-18T09:18:19.023586Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
|
||||
48
.kotlin/errors/errors-1780537656129.log
Normal file
48
.kotlin/errors/errors-1780537656129.log
Normal file
@@ -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-tsmarker7700090853507788345.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)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1780537656460.log
Normal file
48
.kotlin/errors/errors-1780537656460.log
Normal file
@@ -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-tsmarker12680940025563006602.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)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1781138120653.log
Normal file
48
.kotlin/errors/errors-1781138120653.log
Normal file
@@ -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-tsmarker3894271637508823813.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)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1782700916835.log
Normal file
48
.kotlin/errors/errors-1782700916835.log
Normal file
@@ -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-tsmarker16051875768763165132.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)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1782787409833.log
Normal file
48
.kotlin/errors/errors-1782787409833.log
Normal file
@@ -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-tsmarker3580585840179793220.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)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1782788041845.log
Normal file
48
.kotlin/errors/errors-1782788041845.log
Normal file
@@ -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-tsmarker11763075351170172587.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)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1782888714708.log
Normal file
48
.kotlin/errors/errors-1782888714708.log
Normal file
@@ -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-tsmarker3368904538941318214.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)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1782890222939.log
Normal file
48
.kotlin/errors/errors-1782890222939.log
Normal file
@@ -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-tsmarker2940944726750836786.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)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1783384781223.log
Normal file
48
.kotlin/errors/errors-1783384781223.log
Normal file
@@ -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-tsmarker13384034999995465012.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)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1783643668109.log
Normal file
48
.kotlin/errors/errors-1783643668109.log
Normal file
@@ -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-tsmarker11134052769962658558.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)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1783645418169.log
Normal file
48
.kotlin/errors/errors-1783645418169.log
Normal file
@@ -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-tsmarker4236714666597388016.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)
|
||||
|
||||
|
||||
48
.kotlin/errors/errors-1783645640346.log
Normal file
48
.kotlin/errors/errors-1783645640346.log
Normal file
@@ -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-tsmarker12754528945444950713.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)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.defenseapplication"
|
||||
namespace = "com.ckkj.defense_device"
|
||||
compileSdk {
|
||||
version = release(36) {
|
||||
minorApiLevel = 1
|
||||
@@ -11,9 +11,9 @@ android {
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.example.defenseapplication"
|
||||
applicationId = "com.ckkj.defense_device"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
targetSdk = 30
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
@@ -36,6 +36,11 @@ android {
|
||||
buildFeatures {
|
||||
viewBinding=true
|
||||
}
|
||||
lint {
|
||||
disable += "ExpiredTargetSdkVersion"
|
||||
checkReleaseBuilds = false
|
||||
abortOnError = false
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -69,14 +74,8 @@ dependencies {
|
||||
// Kotlin 协程
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
|
||||
|
||||
// CameraX 用于相机预览
|
||||
implementation("androidx.camera:camera-camera2:1.3.0")
|
||||
implementation("androidx.camera:camera-lifecycle:1.3.0")
|
||||
implementation("androidx.camera:camera-view:1.3.0")
|
||||
// Google ML Kit 人脸检测
|
||||
implementation("com.google.mlkit:face-detection:16.1.5")
|
||||
// 图形绘制库(绘制人脸框)
|
||||
implementation("com.github.bumptech.glide:glide:4.15.1")
|
||||
//Glide 依赖
|
||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
||||
// ZXing 二维码扫描库
|
||||
@@ -87,8 +86,6 @@ dependencies {
|
||||
implementation("com.geyifeng.immersionbar:immersionbar-ktx:3.2.2")
|
||||
implementation("com.wdullaer:materialdatetimepicker:4.2.3") // 经典稳定
|
||||
implementation("androidx.core:core-ktx:1.12.0")
|
||||
// Android-PickerView 时间选择器
|
||||
implementation("com.contrarywind:Android-PickerView:4.1.9")
|
||||
//二维码三方库
|
||||
implementation("com.github.maning0303:MNMLKitScanner:V1.0.4")
|
||||
implementation("com.google.mlkit:barcode-scanning:17.0.2")
|
||||
@@ -101,8 +98,10 @@ dependencies {
|
||||
implementation("com.yanzhenjie.recyclerview:x:1.3.2")
|
||||
//Android-PickerView-时间弹窗
|
||||
implementation("com.contrarywind:Android-PickerView:4.1.9")
|
||||
//基于exoPlayer 自定义播放器 JPlayer支持功能
|
||||
implementation("com.ycjiang:VideoPlayModule-Lite:2.3.61")
|
||||
// GSYVideoPlayer
|
||||
implementation("io.github.carguo:gsyvideoplayer:13.0.0")
|
||||
//下载
|
||||
implementation("io.github.chiclaim:downloader:1.0.2")
|
||||
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication
|
||||
package com.ckkj.defense_device
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
@@ -22,17 +22,36 @@
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/loge"
|
||||
android:icon="@mipmap/logo"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.DefenseApplication">
|
||||
<activity
|
||||
android:name=".personal.CancelAccountActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".personal.SettingsMenusActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".home.StartActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".personal.LoginPasswordActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".personal.InvitationCodeActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".personal.JoinFamilyInviteActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".liveVideo.StrikePositionActivity"
|
||||
android:exported="false" />
|
||||
@@ -90,6 +109,7 @@
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".liveVideo.LiveVideoActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".home.SetNameActivity"
|
||||
@@ -126,13 +146,7 @@
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".login.LoginActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
android:exported="false" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
|
||||
41
app/src/main/java/com/ckkj/defense_device/MyApplication.kt
Normal file
41
app/src/main/java/com/ckkj/defense_device/MyApplication.kt
Normal file
@@ -0,0 +1,41 @@
|
||||
package com.ckkj.defense_device
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import com.blankj.utilcode.util.Utils
|
||||
import com.ckkj.defense_device.utils.LanguageUtil
|
||||
// _ooOoo_
|
||||
// o8888888o
|
||||
// 88" . "88
|
||||
// (| -_- |)
|
||||
// O\ = /O
|
||||
// ____/`---'\____
|
||||
// . ' \\| |// `.
|
||||
// / \\||| : |||// \
|
||||
// / _||||| -:- |||||- \
|
||||
// | | \\\ - /// | |
|
||||
// | \_| ''\---/'' | |
|
||||
// \ .-\__ `-` ___/-. /
|
||||
// ___`. .' /--.--\ `. . __
|
||||
// ."" '< `.___\_<|>_/___.' >'"".
|
||||
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
|
||||
// \ \ `-. \_ __\ /__ _/ .-` / /
|
||||
// ======`-.____`-.___\_____/___.-`____.-'======
|
||||
// `=---='
|
||||
//
|
||||
// 佛祖保佑 永无BUG
|
||||
|
||||
class MyApplication : Application() {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
Utils.init(this) // 初始化 AndroidUtilCode
|
||||
LanguageUtil.init(this)
|
||||
}
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
// 在应用启动时应用语言设置
|
||||
val context = LanguageUtil.attachBaseContext(base)
|
||||
super.attachBaseContext(context)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.adapter
|
||||
package com.ckkj.defense_device.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@@ -6,7 +6,7 @@ import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.R
|
||||
import com.ckkj.defense_device.R
|
||||
|
||||
data class Device(
|
||||
val name: String,
|
||||
@@ -18,6 +18,8 @@ class AddDeviceAdapter(
|
||||
private val onItemClick: (Device) -> Unit
|
||||
) : RecyclerView.Adapter<AddDeviceAdapter.ViewHolder>() {
|
||||
|
||||
private val defaultIcons = listOf(R.mipmap.img1, R.mipmap.img2, R.mipmap.img3)
|
||||
|
||||
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
val ivIcon: ImageView = itemView.findViewById(R.id.ivDeviceIcon2)
|
||||
val tvName: TextView = itemView.findViewById(R.id.tvDeviceName2)
|
||||
@@ -47,7 +49,9 @@ class AddDeviceAdapter(
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val device = devices[position]
|
||||
holder.tvName.text = device.name
|
||||
holder.ivIcon.setImageResource(R.drawable.img)
|
||||
|
||||
val iconResId = defaultIcons[position % defaultIcons.size]
|
||||
holder.ivIcon.setImageResource(iconResId)
|
||||
|
||||
// 点击事件
|
||||
holder.itemView.setOnClickListener { onItemClick(device) }
|
||||
@@ -1,11 +1,10 @@
|
||||
package com.example.defenseapplication.adapter
|
||||
package com.ckkj.defense_device.adapter
|
||||
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.ItemAddLinkedUserBinding
|
||||
import com.ckkj.defense_device.databinding.ItemAddLinkedUserBinding
|
||||
|
||||
data class UserItem(val name: String, val phone: String, val userId: String = "")
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.example.defenseapplication.adapter
|
||||
package com.ckkj.defense_device.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.bean.DeviceAlarmBean
|
||||
import com.example.defenseapplication.databinding.ItemAlarmLogBinding
|
||||
import com.ckkj.defense_device.bean.DeviceAlarmBean
|
||||
import com.ckkj.defense_device.databinding.ItemAlarmLogBinding
|
||||
|
||||
class AlarmLogAdapter(
|
||||
private val items: List<DeviceAlarmBean>,
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.example.defenseapplication.adapter
|
||||
package com.ckkj.defense_device.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.example.defenseapplication.bean.DeviceAlarmBean
|
||||
import com.example.defenseapplication.databinding.ItemAlarmLogHorizontalBinding
|
||||
import com.ckkj.defense_device.bean.DeviceAlarmBean
|
||||
import com.ckkj.defense_device.databinding.ItemAlarmLogHorizontalBinding
|
||||
|
||||
class AlarmLogHorizontalAdapter(
|
||||
private val items: List<DeviceAlarmBean>,
|
||||
@@ -1,27 +1,20 @@
|
||||
package com.example.defenseapplication.adapter
|
||||
package com.ckkj.defense_device.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.ItemDeviceBinding
|
||||
|
||||
data class DeviceUi(
|
||||
val name: String,
|
||||
val status: String,
|
||||
val deviceId: String = ""
|
||||
) {
|
||||
val isOnline: Boolean
|
||||
get() = status == "1"
|
||||
}
|
||||
import com.bumptech.glide.Glide
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.bean.DeviceBean
|
||||
import com.ckkj.defense_device.databinding.ItemDeviceBinding
|
||||
|
||||
class DeviceAdapter(
|
||||
private val onItemClick: (DeviceUi) -> Unit = {}
|
||||
private val onItemClick: (DeviceBean) -> Unit = {}
|
||||
) : RecyclerView.Adapter<DeviceAdapter.DeviceViewHolder>() {
|
||||
|
||||
private val items = mutableListOf<DeviceUi>()
|
||||
private val items = mutableListOf<DeviceBean>()
|
||||
|
||||
fun submitList(deviceList: List<DeviceUi>) {
|
||||
fun submitList(deviceList: List<DeviceBean>) {
|
||||
items.clear()
|
||||
items.addAll(deviceList)
|
||||
notifyDataSetChanged()
|
||||
@@ -33,15 +26,25 @@ class DeviceAdapter(
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: DeviceViewHolder, position: Int) {
|
||||
holder.bind(items[position])
|
||||
holder.bind(items[position], position)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = items.size
|
||||
|
||||
private val defaultIcons = listOf(R.mipmap.img1, R.mipmap.img2, R.mipmap.img3)
|
||||
|
||||
inner class DeviceViewHolder(private val binding: ItemDeviceBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: DeviceUi) {
|
||||
fun bind(item: DeviceBean, position: Int) {
|
||||
if (item.deviceImg.isNullOrEmpty()) {
|
||||
val iconResId = defaultIcons[position % defaultIcons.size]
|
||||
binding.ivDeviceIcon.setImageResource(iconResId)
|
||||
} else {
|
||||
Glide.with(binding.root.context)
|
||||
.load(item.deviceImg)
|
||||
.into(binding.ivDeviceIcon)
|
||||
}
|
||||
binding.tvDeviceType.text = item.name
|
||||
when (item.status) {
|
||||
"1" -> {
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.example.defenseapplication.adapter
|
||||
package com.ckkj.defense_device.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.bean.FamilyBean
|
||||
import com.example.defenseapplication.databinding.ItemFamilyBinding
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.bean.FamilyBean
|
||||
import com.ckkj.defense_device.databinding.ItemFamilyBinding
|
||||
|
||||
class FamilyAdapter(
|
||||
private val onItemClick: (String) -> Unit
|
||||
@@ -64,7 +64,7 @@ class FamilyAdapter(
|
||||
binding.tvFamilyName.setTextColor(binding.root.context.getColor(R.color.white))
|
||||
binding.tvFamilyRole.setTextColor(binding.root.context.getColor(R.color.white))
|
||||
binding.ivCheck.visibility = View.VISIBLE
|
||||
binding.ivCheck.setImageResource(R.drawable.ic_check_white)
|
||||
binding.ivCheck.setImageResource(R.mipmap.ic_check_white)
|
||||
} else {
|
||||
binding.layoutFamilyItem.setBackgroundResource(0)
|
||||
binding.tvFamilyName.setTextColor(binding.root.context.getColor(R.color.black))
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.example.defenseapplication.adapter
|
||||
package com.ckkj.defense_device.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.ItemSwitchFamilyBinding
|
||||
import com.example.defenseapplication.model.FamilyItem
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.databinding.ItemSwitchFamilyBinding
|
||||
import com.ckkj.defense_device.model.FamilyItem
|
||||
|
||||
class FamilySwitchAdapter(
|
||||
private var familyList: List<FamilyItem>,
|
||||
@@ -1,11 +1,10 @@
|
||||
package com.example.defenseapplication.adapter
|
||||
package com.ckkj.defense_device.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.ItemLinkedUserBinding
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.databinding.ItemLinkedUserBinding
|
||||
|
||||
data class LinkedUser(
|
||||
val userId: String,
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.example.defenseapplication.adapter
|
||||
package com.ckkj.defense_device.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.databinding.ItemMessageGroupTitleBinding
|
||||
import com.example.defenseapplication.databinding.ItemMessageNoticeBinding
|
||||
import com.ckkj.defense_device.databinding.ItemMessageGroupTitleBinding
|
||||
import com.ckkj.defense_device.databinding.ItemMessageNoticeBinding
|
||||
|
||||
sealed class MessageListItem {
|
||||
data class Header(val title: String) : MessageListItem()
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.example.defenseapplication.adapter
|
||||
package com.ckkj.defense_device.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.databinding.ItemWifiBinding
|
||||
import com.ckkj.defense_device.databinding.ItemWifiBinding
|
||||
|
||||
class WifiListAdapter(
|
||||
wifiList: List<String>,
|
||||
@@ -39,14 +40,25 @@ class WifiListAdapter(
|
||||
override fun getItemCount(): Int = wifiList.size
|
||||
|
||||
fun updateData(newList: List<String>) {
|
||||
val oldList = wifiList.toList()
|
||||
val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
|
||||
override fun getOldListSize() = oldList.size
|
||||
override fun getNewListSize() = newList.size
|
||||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
|
||||
oldList[oldItemPosition] == newList[newItemPosition]
|
||||
|
||||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
|
||||
oldList[oldItemPosition] == newList[newItemPosition]
|
||||
})
|
||||
wifiList.clear()
|
||||
wifiList.addAll(newList)
|
||||
notifyDataSetChanged()
|
||||
diffResult.dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
fun addData(newList: List<String>) {
|
||||
val startPosition = wifiList.size
|
||||
val newItems = newList.filter { !wifiList.contains(it) }
|
||||
if (newItems.isEmpty()) return
|
||||
wifiList.addAll(newItems)
|
||||
notifyItemRangeInserted(startPosition, newItems.size)
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.example.defenseapplication.base
|
||||
package com.ckkj.defense_device.base
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.utils.ActivityManager
|
||||
import com.example.defenseapplication.utils.LanguageUtil
|
||||
import com.ckkj.defense_device.utils.ActivityManager
|
||||
import com.ckkj.defense_device.utils.LanguageUtil
|
||||
|
||||
open class BaseActivity : AppCompatActivity() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class AddDeviceBean(
|
||||
val deviceEm: String? = null,//设备型号
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class AddDeviceUserRequest(
|
||||
val deviceId: String,
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
/**
|
||||
* 统一返回数据基类(根据你的后端实际字段调整)
|
||||
*/
|
||||
data class BaseInfo(
|
||||
val message: String? = null,
|
||||
val msg: String? = null,
|
||||
val code: Int = 0,
|
||||
val data: Any? = null
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
class DeleteBean {
|
||||
var deviceId: String? = null
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class DeleteDeviceUserRequest(
|
||||
val userId: String,
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class DeviceAlarmResponse(
|
||||
val total: Int,
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class DeviceBean(
|
||||
val alertAudio: String? = null,//告警播放
|
||||
@@ -9,11 +9,11 @@ data class DeviceBean(
|
||||
val deviceFamilyId: String? = null,
|
||||
val deviceImg: String? = null,
|
||||
val deviceName: String? = null,//设备名称
|
||||
val deviceNo: String? = null,//设备编号
|
||||
val deviceSn: String? = null,//设备序列号
|
||||
val deviceNo: String = "",//设备编号
|
||||
val deviceSn: String = "",//设备序列号
|
||||
val endTime: String? = null,//自动布放结束时间
|
||||
val expirationTime: String? = null,
|
||||
val fwVer: String? = null,//固件版本
|
||||
val fwVer: String= "",//固件版本
|
||||
val id: String? = null,
|
||||
val light: String? = null,//强光开启
|
||||
val patternPerception: String? = null,//识别模式
|
||||
@@ -27,4 +27,13 @@ data class DeviceBean(
|
||||
val wifiPassword: String? = null,//WiFi密码
|
||||
val workMode: String? = null,//工作模式 0-自动 1-半自动
|
||||
val optionPassword: String? = null, //操作密码
|
||||
)
|
||||
) {
|
||||
val deviceId: String
|
||||
get() = id ?: ""
|
||||
|
||||
val name: String
|
||||
get() = deviceName ?: ""
|
||||
|
||||
val isOnline: Boolean
|
||||
get() = status == "1"
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class DeviceUserBean(
|
||||
val createDept: Int ? = null, //创建部门
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class FamilyBean(
|
||||
val id: String,
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class FamilyMembersBean(
|
||||
val id: String? = null, // ID
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class GetCodeBean<T> (
|
||||
val code:Int,
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class InviterInfoBean(
|
||||
val nickName: String? = null,
|
||||
val idCard: String? = null,
|
||||
val phonenumber: String? = null,
|
||||
val avatar: String? = null,
|
||||
val id: String? = null,
|
||||
val parentId: String? = null,
|
||||
val userId: String? = null,
|
||||
val mac: String? = null,
|
||||
val status: String? = null,
|
||||
) {
|
||||
fun resolveParentId(): String? =
|
||||
parentId?.takeIf { it.isNotBlank() }
|
||||
?: userId?.takeIf { it.isNotBlank() }
|
||||
?: id?.takeIf { it.isNotBlank() }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
|
||||
data class JoinTheFamilyBean(
|
||||
val parentId: String,
|
||||
val inviteCode: String,
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class MessageListResponse(
|
||||
val total: Int,
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class ObtainInviterInformationBean(
|
||||
val nickName: String? = null,
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class ObtainInviterInformationRequest(
|
||||
val childId: String
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class RecommendationCodeBean(
|
||||
val inviteCode: String? = null,
|
||||
val code: String? = null,
|
||||
val expireTime: Long? = null,
|
||||
val expire: Long? = null
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class SelectInviterInfoBean(
|
||||
val code: String
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class SwitchFamilyRequest(
|
||||
val clientId: String,
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class UpdateFamilyUserRequest(
|
||||
val id: String,
|
||||
val optionPassword: String,
|
||||
val optionStatus: String,
|
||||
val status: String,
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class UpdatePassword(
|
||||
val oldPassword: String,
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class UpdateUserInfo(
|
||||
val userId: String?=null,
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class UploadResponse(
|
||||
val code: Int,
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.bean
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class VerifyOptionPasswordRequest(
|
||||
val optionPassword: String
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class VideoStreamInfo(
|
||||
val deviceNo: String,
|
||||
val streamId: String,
|
||||
val app: String,
|
||||
val online: Boolean,
|
||||
val pushUrl: String,
|
||||
val playToken: String,
|
||||
val expireAt: String,
|
||||
val playUrls:playUrls,
|
||||
val expireSeconds: Int,
|
||||
)
|
||||
class playUrls(
|
||||
val flv: String,
|
||||
val hls: String,
|
||||
val rtmp: String,
|
||||
val rtsp: String,
|
||||
val webrtc: String,
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.ckkj.defense_device.bean
|
||||
|
||||
data class VideoStreamRequest(
|
||||
val deviceNo: String
|
||||
)
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.example.defenseapplication.home
|
||||
package com.ckkj.defense_device.home
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
@@ -14,10 +13,10 @@ import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.adapter.AddDeviceAdapter
|
||||
import com.example.defenseapplication.adapter.Device
|
||||
import com.example.defenseapplication.databinding.AddDeviceActivityBinding
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.adapter.AddDeviceAdapter
|
||||
import com.ckkj.defense_device.adapter.Device
|
||||
import com.ckkj.defense_device.databinding.AddDeviceActivityBinding
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.maning.mlkitscanner.scan.MNScanManager
|
||||
import com.maning.mlkitscanner.scan.callback.act.MNScanCallback
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.home
|
||||
package com.ckkj.defense_device.home
|
||||
|
||||
import android.Manifest
|
||||
import android.content.BroadcastReceiver
|
||||
@@ -23,10 +23,10 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.adapter.WifiListAdapter
|
||||
import com.example.defenseapplication.databinding.AddFamilyActivityBinding
|
||||
import com.example.defenseapplication.databinding.DialogWifiListBinding
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.adapter.WifiListAdapter
|
||||
import com.ckkj.defense_device.databinding.AddFamilyActivityBinding
|
||||
import com.ckkj.defense_device.databinding.DialogWifiListBinding
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
//选择Wi-Fi
|
||||
class AddFamilyActivity : AppCompatActivity() {
|
||||
@@ -144,10 +144,6 @@ class AddFamilyActivity : AppCompatActivity() {
|
||||
}
|
||||
dialogBinding.rvWifiList.adapter = wifiListAdapter
|
||||
|
||||
dialogBinding.swipeRefreshLayout.setOnRefreshListener {
|
||||
refreshWifiList(dialogBinding)
|
||||
}
|
||||
|
||||
dialogBinding.rvWifiList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
@@ -168,16 +164,6 @@ class AddFamilyActivity : AppCompatActivity() {
|
||||
return rect.height()
|
||||
}
|
||||
|
||||
private fun refreshWifiList(dialogBinding: DialogWifiListBinding) {
|
||||
dialogBinding.swipeRefreshLayout.isRefreshing = true
|
||||
handler.postDelayed({
|
||||
wifiManager.startScan()
|
||||
val newWifiList = getWifiList()
|
||||
wifiListAdapter?.updateData(newWifiList)
|
||||
dialogBinding.swipeRefreshLayout.isRefreshing = false
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
private fun loadMoreWifiList() {
|
||||
isLoadingMore = true
|
||||
handler.postDelayed({
|
||||
@@ -204,12 +190,8 @@ class AddFamilyActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun updateWifiList() {
|
||||
popupWindow?.contentView?.findViewById<androidx.recyclerview.widget.RecyclerView>(R.id.rvWifiList)?.let { recyclerView ->
|
||||
val wifiList = getWifiList()
|
||||
recyclerView.adapter = WifiListAdapter(wifiList) { wifiName ->
|
||||
binding.etWifiName.setText(wifiName)
|
||||
popupWindow?.dismiss()
|
||||
}
|
||||
popupWindow?.contentView?.findViewById<androidx.recyclerview.widget.RecyclerView>(R.id.rvWifiList)?.let {
|
||||
wifiListAdapter?.updateData(getWifiList())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.home
|
||||
package com.ckkj.defense_device.home
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.AnimationDrawable
|
||||
@@ -6,14 +6,9 @@ import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.AddDeviceActivityBinding
|
||||
import com.example.defenseapplication.databinding.ConnectDeviceActivityBinding
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.databinding.ConnectDeviceActivityBinding
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
//连接设备
|
||||
class ConnectDeviceActivity : AppCompatActivity() {
|
||||
@@ -1,17 +1,17 @@
|
||||
package com.example.defenseapplication.home
|
||||
package com.ckkj.defense_device.home
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.base.BaseActivity
|
||||
import com.example.defenseapplication.databinding.HomeActivityBinding
|
||||
import com.example.defenseapplication.databinding.HomeMenuFragmentBinding
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.base.BaseActivity
|
||||
import com.ckkj.defense_device.databinding.HomeActivityBinding
|
||||
|
||||
class HomeActivity : BaseActivity() {
|
||||
|
||||
companion object {
|
||||
const val EXTRA_REFRESH = "extra_refresh"
|
||||
}
|
||||
// ViewBinding 核心对象
|
||||
private lateinit var binding: HomeActivityBinding
|
||||
|
||||
@@ -37,10 +37,10 @@ class HomeActivity : BaseActivity() {
|
||||
binding.tabHome.setOnClickListener {
|
||||
switchFragment(homeMenuFragment)
|
||||
// 切换图标 + 文字颜色
|
||||
binding.ivHome.setImageResource(R.drawable.home_checked)
|
||||
binding.ivHome.setImageResource(R.mipmap.home_checked)
|
||||
binding.tvHome.setTextColor(resources.getColor(R.color.ic_selected))
|
||||
|
||||
binding.ivProfile.setImageResource(R.drawable.profile)
|
||||
binding.ivProfile.setImageResource(R.mipmap.profile)
|
||||
binding.tvProfile.setTextColor(resources.getColor(R.color.ic_normal))
|
||||
}
|
||||
|
||||
@@ -48,12 +48,34 @@ class HomeActivity : BaseActivity() {
|
||||
binding.tabProfile.setOnClickListener {
|
||||
switchFragment(personalFragment)
|
||||
// 切换图标 + 文字颜色
|
||||
binding.ivHome.setImageResource(R.drawable.home)
|
||||
binding.ivHome.setImageResource(R.mipmap.home)
|
||||
binding.tvHome.setTextColor(resources.getColor(R.color.ic_normal))
|
||||
|
||||
binding.ivProfile.setImageResource(R.drawable.profile_checked)
|
||||
binding.ivProfile.setImageResource(R.mipmap.profile_checked)
|
||||
binding.tvProfile.setTextColor(resources.getColor(R.color.ic_selected))
|
||||
}
|
||||
|
||||
handleRefreshIntent(intent)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
super.onNewIntent(intent)
|
||||
if (intent != null) {
|
||||
setIntent(intent)
|
||||
handleRefreshIntent(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRefreshIntent(intent: Intent) {
|
||||
if (intent.getBooleanExtra(EXTRA_REFRESH, false)) {
|
||||
intent.removeExtra(EXTRA_REFRESH)
|
||||
switchFragment(homeMenuFragment)
|
||||
binding.ivHome.setImageResource(R.mipmap.home_checked)
|
||||
binding.tvHome.setTextColor(resources.getColor(R.color.ic_selected))
|
||||
binding.ivProfile.setImageResource(R.mipmap.profile)
|
||||
binding.tvProfile.setTextColor(resources.getColor(R.color.ic_normal))
|
||||
homeMenuFragment.refreshHomeData()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.home
|
||||
package com.ckkj.defense_device.home
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
@@ -7,7 +7,7 @@ import android.content.pm.PackageManager
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
@@ -21,23 +21,27 @@ import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.adapter.DeviceAdapter
|
||||
import com.example.defenseapplication.adapter.DeviceUi
|
||||
import com.example.defenseapplication.adapter.FamilyAdapter
|
||||
import com.example.defenseapplication.bean.DeviceBean
|
||||
import com.example.defenseapplication.bean.FamilyBean
|
||||
import com.example.defenseapplication.bean.SwitchFamilyRequest
|
||||
import com.example.defenseapplication.databinding.HomeMenuFragmentBinding
|
||||
import com.example.defenseapplication.liveVideo.LiveVideoActivity
|
||||
import com.example.defenseapplication.utils.DeviceIdEvent
|
||||
import com.example.defenseapplication.utils.DeviceUpdateEvent
|
||||
import com.example.defenseapplication.utils.FamilySwitchEvent
|
||||
import com.example.defenseapplication.utils.MessageStatusManager
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.utils.UserinfoUtil
|
||||
import com.example.defenseapplication.view.DefenseDialogs
|
||||
import com.example.defenseapplication.view.showDefenseDialog
|
||||
import com.alibaba.sdk.android.emas.g
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.adapter.DeviceAdapter
|
||||
import com.ckkj.defense_device.adapter.FamilyAdapter
|
||||
import com.ckkj.defense_device.bean.DeviceBean
|
||||
import com.ckkj.defense_device.bean.FamilyBean
|
||||
import com.ckkj.defense_device.bean.SwitchFamilyRequest
|
||||
import com.ckkj.defense_device.bean.SelectInviterInfoBean
|
||||
import com.ckkj.defense_device.databinding.HomeMenuFragmentBinding
|
||||
import com.ckkj.defense_device.liveVideo.LiveVideoActivity
|
||||
import com.ckkj.defense_device.personal.JoinFamilyInviteActivity
|
||||
import com.ckkj.defense_device.utils.DeviceIdEvent
|
||||
import com.ckkj.defense_device.utils.DeviceUpdateEvent
|
||||
import com.ckkj.defense_device.utils.FamilySwitchEvent
|
||||
import com.ckkj.defense_device.utils.MessageStatusManager
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.utils.UserinfoUtil
|
||||
import com.ckkj.defense_device.view.DefenseDialogs
|
||||
import com.ckkj.defense_device.view.LoadingDialog
|
||||
import com.ckkj.defense_device.view.PullRefreshLayout
|
||||
import com.ckkj.defense_device.view.showDefenseDialog
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.maning.mlkitscanner.scan.MNScanManager
|
||||
import com.maning.mlkitscanner.scan.callback.act.MNScanCallback
|
||||
@@ -45,6 +49,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.json.JSONObject
|
||||
//主页碎片
|
||||
class HomeMenuFragment : Fragment() {
|
||||
// ViewBinding
|
||||
@@ -59,6 +64,9 @@ class HomeMenuFragment : Fragment() {
|
||||
private val pageSize = 10
|
||||
private var hasMore = true
|
||||
private var isLoading = false
|
||||
private var loadingDialog: LoadingDialog? = null
|
||||
private var lastNoMoreToastTime: Long = 0L
|
||||
private val noMoreToastInterval: Long = 1500L
|
||||
|
||||
private val requestPermissionsLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.RequestMultiplePermissions()
|
||||
@@ -122,23 +130,86 @@ class HomeMenuFragment : Fragment() {
|
||||
MNScanManager.RESULT_SUCCESS -> {
|
||||
val result = data?.getStringArrayListExtra(MNScanManager.INTENT_KEY_RESULT_SUCCESS)
|
||||
if (!result.isNullOrEmpty()) {
|
||||
ToastUtils.showToast(requireContext(), "扫码成功: $result")
|
||||
val inviteCode = parseInviteCode(result[0])
|
||||
if (inviteCode.isNullOrEmpty()) {
|
||||
Toast.makeText(requireContext(), "无效的邀请码", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
ToastUtils.showToast(requireContext(), "扫码结果为空")
|
||||
fetchInviterInfo(inviteCode)
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "扫码结果为空", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
MNScanManager.RESULT_FAIL -> {
|
||||
val error = data?.getStringExtra(MNScanManager.INTENT_KEY_RESULT_ERROR)
|
||||
ToastUtils.showToast(requireContext(), "扫码失败: $error")
|
||||
Toast.makeText(requireContext(), "扫码失败: $error", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
MNScanManager.RESULT_CANCLE -> {
|
||||
ToastUtils.showToast(requireContext(), "扫码取消")
|
||||
Toast.makeText(requireContext(), "扫码取消", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun parseInviteCode(scanResult: String): String? {
|
||||
val trimmed = scanResult.trim()
|
||||
if (trimmed.isEmpty()) return null
|
||||
return try {
|
||||
if (trimmed.startsWith("{")) {
|
||||
JSONObject(trimmed).optString("code").takeIf { it.isNotEmpty() }
|
||||
} else {
|
||||
trimmed
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
trimmed
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchInviterInfo(inviteCode: String) {
|
||||
val loadingDialog = LoadingDialog(requireActivity()).setMessage(this.getString(R.string.loading)).apply { show() }
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService()
|
||||
.selectInviterInfo(SelectInviterInfoBean(code = inviteCode))
|
||||
withContext(Dispatchers.Main) {
|
||||
loadingDialog.dismiss()
|
||||
if (response.code == 200 && response.data != null) {
|
||||
val inviter = response.data
|
||||
val parentId = inviter.resolveParentId()
|
||||
if (parentId.isNullOrEmpty()) {
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
getString(R.string.network_error),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
return@withContext
|
||||
}
|
||||
val intent = Intent(requireContext(), JoinFamilyInviteActivity::class.java).apply {
|
||||
putExtra(JoinFamilyInviteActivity.EXTRA_INVITE_CODE, inviteCode)
|
||||
putExtra(JoinFamilyInviteActivity.EXTRA_NICK_NAME, inviter.nickName)
|
||||
putExtra(JoinFamilyInviteActivity.EXTRA_AVATAR, inviter.avatar)
|
||||
putExtra(JoinFamilyInviteActivity.EXTRA_PARENT_ID, parentId)
|
||||
putExtra(JoinFamilyInviteActivity.EXTRA_USER_ID, inviter.userId)
|
||||
}
|
||||
startActivity(intent)
|
||||
} else {
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
response.msg.ifBlank { getString(R.string.network_error) },
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
loadingDialog.dismiss()
|
||||
Toast.makeText(requireContext(), R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val unreadCountChangeListener = object : MessageStatusManager.UnreadCountChangeListener {
|
||||
override fun onUnreadCountChanged(count: Int) {
|
||||
updateUnreadCountUI(count)
|
||||
@@ -197,12 +268,7 @@ class HomeMenuFragment : Fragment() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// 为 LinearLayout 设置渐变背景
|
||||
setGradientBackground(
|
||||
view = binding.gradientLayout,
|
||||
startColor = Color.parseColor("#EBDCED"),
|
||||
endColor = Color.parseColor("#CAF4FF")
|
||||
)
|
||||
binding.gradientLayout.setBackgroundColor(Color.TRANSPARENT)
|
||||
binding.message.setOnClickListener {
|
||||
val intent = Intent(requireContext(), MessageActivity::class.java)
|
||||
startActivity(intent)
|
||||
@@ -236,9 +302,11 @@ class HomeMenuFragment : Fragment() {
|
||||
)
|
||||
}
|
||||
|
||||
binding.swipeRefreshLayout.setOnRefreshListener {
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(object : PullRefreshLayout.OnRefreshListener {
|
||||
override fun onRefresh() {
|
||||
refreshDeviceList()
|
||||
}
|
||||
})
|
||||
|
||||
binding.rvDeviceList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
@@ -246,9 +314,24 @@ class HomeMenuFragment : Fragment() {
|
||||
val layoutManager = recyclerView.layoutManager as GridLayoutManager
|
||||
val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
|
||||
val totalItemCount = layoutManager.itemCount
|
||||
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
|
||||
|
||||
if (firstVisibleItemPosition == 0) {
|
||||
val firstChild = layoutManager.findViewByPosition(0)
|
||||
firstChild?.let { child ->
|
||||
val top = child.top
|
||||
if (top >= 0) {
|
||||
val offset = (top.toFloat() / dpToPx(80f)).coerceIn(0f, 1f)
|
||||
binding.gradientLayout.translationY = -offset * dpToPx(20f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isLoading && hasMore && lastVisibleItemPosition >= totalItemCount - 1 && dy > 0) {
|
||||
loadMoreDevices()
|
||||
} else if (!hasMore && !isLoading && lastVisibleItemPosition >= totalItemCount - 1
|
||||
&& dy > 0 && totalItemCount > 0) {
|
||||
showNoMoreToast()
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -285,6 +368,10 @@ class HomeMenuFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshHomeData() {
|
||||
fetchFamilyList()
|
||||
}
|
||||
|
||||
private fun fetchFamilyList() {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
@@ -321,18 +408,22 @@ class HomeMenuFragment : Fragment() {
|
||||
Log.d("HomeMenuFragment", "canViewDevice = $canViewDevice")
|
||||
if (canViewDevice) {
|
||||
binding.tvDeviceTitle.visibility = View.VISIBLE
|
||||
binding.swipeRefreshLayout.visibility = View.VISIBLE
|
||||
binding.rvDeviceList.visibility = View.VISIBLE
|
||||
binding.message.visibility = View.VISIBLE
|
||||
binding.addFamily.visibility = View.VISIBLE
|
||||
binding.add.visibility = View.VISIBLE
|
||||
binding.layoutNoPermission.visibility = View.GONE
|
||||
binding.layoutNoNetwork.visibility = View.GONE
|
||||
} else {
|
||||
binding.tvDeviceTitle.visibility = View.GONE
|
||||
binding.swipeRefreshLayout.visibility = View.GONE
|
||||
binding.rvDeviceList.visibility = View.GONE
|
||||
binding.message.visibility = View.GONE
|
||||
binding.addFamily.visibility = View.GONE
|
||||
binding.add.visibility = View.GONE
|
||||
binding.layoutNoPermission.visibility = View.VISIBLE
|
||||
binding.layoutNoNetwork.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,7 +447,7 @@ class HomeMenuFragment : Fragment() {
|
||||
canViewDevice = userInfo?.role == "appadmin" && familyBean.role != "member"
|
||||
updateAdminUI()
|
||||
updateFamilyDisplayText(familyName)
|
||||
fetchDeviceList()
|
||||
fetchDeviceList(showLoading = true)
|
||||
FamilySwitchEvent.notifyFamilySwitched(familyName)
|
||||
} else {
|
||||
Toast.makeText(requireContext(), response.msg, Toast.LENGTH_SHORT).show()
|
||||
@@ -370,15 +461,20 @@ class HomeMenuFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchDeviceList(page: Int = 1, isLoadMore: Boolean = false) {
|
||||
private fun fetchDeviceList(page: Int = 1, isLoadMore: Boolean = false, showLoading: Boolean = false) {
|
||||
if (!canViewDevice || isLoading) return
|
||||
|
||||
isLoading = true
|
||||
|
||||
loadingDialog = if (showLoading) LoadingDialog(requireActivity()).setMessage(getString(R.string.loading)).apply { show() } else null
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().getDeviceList()
|
||||
withContext(Dispatchers.Main) {
|
||||
if (!isAdded) return@withContext
|
||||
loadingDialog?.dismiss()
|
||||
loadingDialog = null
|
||||
Log.d("DeviceList", "code = ${response.code}, data = ${response.data}")
|
||||
if (response.code == 200 && response.data != null) {
|
||||
val newDevices = response.data
|
||||
@@ -390,32 +486,47 @@ class HomeMenuFragment : Fragment() {
|
||||
hasMore = newDevices.size >= pageSize
|
||||
}
|
||||
Log.d("DeviceList", "deviceBeanList size = ${deviceBeanList.size}")
|
||||
showDeviceContent()
|
||||
updateDeviceList()
|
||||
} else {
|
||||
Toast.makeText(requireContext(), response.msg, Toast.LENGTH_SHORT).show()
|
||||
noNetwork()
|
||||
val errorMsg = response.msg.ifBlank { getString(R.string.network_error) }
|
||||
Toast.makeText(requireContext(), errorMsg, Toast.LENGTH_SHORT).show()
|
||||
if (isLoadMore) {
|
||||
hasMore = false
|
||||
}
|
||||
}
|
||||
isLoading = false
|
||||
binding.swipeRefreshLayout.finishRefresh()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
if (!isAdded) return@withContext
|
||||
loadingDialog?.dismiss()
|
||||
loadingDialog = null
|
||||
noNetwork()
|
||||
Toast.makeText(requireContext(), R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
isLoading = false
|
||||
if (isLoadMore) {
|
||||
hasMore = false
|
||||
}
|
||||
binding.swipeRefreshLayout.finishRefresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showNoMoreToast() {
|
||||
val now = System.currentTimeMillis()
|
||||
if (now - lastNoMoreToastTime < noMoreToastInterval) return
|
||||
lastNoMoreToastTime = now
|
||||
ToastUtils.showToast(requireContext(), getString(R.string.no_more_data))
|
||||
}
|
||||
|
||||
private fun refreshDeviceList() {
|
||||
currentPage = 1
|
||||
hasMore = true
|
||||
fetchDeviceList(currentPage, false)
|
||||
binding.swipeRefreshLayout.isRefreshing = false
|
||||
}
|
||||
|
||||
private fun loadMoreDevices() {
|
||||
@@ -445,26 +556,38 @@ class HomeMenuFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateDeviceList() {
|
||||
val deviceUiList = deviceBeanList.map {
|
||||
DeviceUi(it.deviceName ?: "", it.status ?: "", it.id ?: "")
|
||||
private fun showDeviceContent() {
|
||||
binding.swipeRefreshLayout.visibility = View.VISIBLE
|
||||
binding.rvDeviceList.visibility = View.VISIBLE
|
||||
binding.layoutNoPermission.visibility = View.GONE
|
||||
binding.layoutNoNetwork.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (deviceUiList.isEmpty()) {
|
||||
private fun noNetwork() {
|
||||
binding.swipeRefreshLayout.visibility = View.GONE
|
||||
binding.rvDeviceList.visibility = View.GONE
|
||||
binding.layoutNoPermission.visibility = View.GONE
|
||||
binding.layoutNoNetwork.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun updateDeviceList() {
|
||||
if (deviceBeanList.isEmpty()) {
|
||||
deviceAdapter.submitList(listOf(
|
||||
DeviceUi(getString(R.string.no_device), "0")
|
||||
DeviceBean(deviceName = getString(R.string.no_device), status = "0")
|
||||
))
|
||||
} else {
|
||||
deviceAdapter.submitList(deviceUiList)
|
||||
deviceAdapter.submitList(deviceBeanList)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onDeviceClicked(device: DeviceUi) {
|
||||
private fun onDeviceClicked(device: DeviceBean) {
|
||||
if (device.isOnline) {
|
||||
DeviceIdEvent.setDeviceId(device.deviceId)
|
||||
val intent = Intent(requireContext(), LiveVideoActivity::class.java)
|
||||
intent.putExtra("device_id", device.deviceId)
|
||||
intent.putExtra("device_name", device.name)
|
||||
intent.putExtra("deviceNo", device.deviceNo)
|
||||
intent.putExtra("light", device.light)
|
||||
startActivity(intent)
|
||||
} else {
|
||||
showDefenseDialog(
|
||||
@@ -481,6 +604,14 @@ class HomeMenuFragment : Fragment() {
|
||||
).toInt()
|
||||
}
|
||||
|
||||
private fun dpToPx(dp: Float): Float {
|
||||
return TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
dp,
|
||||
resources.displayMetrics
|
||||
)
|
||||
}
|
||||
|
||||
private class GridHorizontalSpaceItemDecoration(
|
||||
private val horizontalSpace: Int
|
||||
) : RecyclerView.ItemDecoration() {
|
||||
@@ -501,19 +632,10 @@ class HomeMenuFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun setGradientBackground(
|
||||
view: View,
|
||||
startColor: Int,
|
||||
endColor: Int,
|
||||
orientation: GradientDrawable.Orientation = GradientDrawable.Orientation.TL_BR
|
||||
) {
|
||||
val gradientDrawable = GradientDrawable(orientation, intArrayOf(startColor, endColor))
|
||||
gradientDrawable.gradientType = GradientDrawable.LINEAR_GRADIENT
|
||||
view.background = gradientDrawable
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
loadingDialog?.dismiss()
|
||||
loadingDialog = null
|
||||
binding.rvFamilyList.adapter = null
|
||||
binding.rvDeviceList.adapter = null
|
||||
MessageStatusManager.removeListener(unreadCountChangeListener)
|
||||
@@ -1,15 +1,18 @@
|
||||
package com.example.defenseapplication.home
|
||||
package com.ckkj.defense_device.home
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.adapter.MessageListAdapter
|
||||
import com.example.defenseapplication.adapter.MessageListItem
|
||||
import com.example.defenseapplication.databinding.MessageActivityBinding
|
||||
import com.example.defenseapplication.utils.MessageStatusManager
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.adapter.MessageListAdapter
|
||||
import com.ckkj.defense_device.adapter.MessageListItem
|
||||
import com.ckkj.defense_device.databinding.MessageActivityBinding
|
||||
import com.ckkj.defense_device.utils.MessageStatusManager
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.LoadingDialog
|
||||
import com.ckkj.defense_device.view.PullRefreshLayout
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -19,13 +22,13 @@ import kotlinx.coroutines.withContext
|
||||
class MessageActivity : AppCompatActivity() {
|
||||
private lateinit var binding: MessageActivityBinding
|
||||
private val messageAdapter by lazy { MessageListAdapter() }
|
||||
private lateinit var loadingDialog: LoadingDialog
|
||||
|
||||
private var currentPage = 1
|
||||
private val pageSize = 10
|
||||
private var isLoading = false
|
||||
private var hasMoreData = true
|
||||
private val allMessages = mutableListOf<com.example.defenseapplication.bean.MessageBean>()
|
||||
private var lastLoadedCount = 0
|
||||
private val allMessages = mutableListOf<com.ckkj.defense_device.bean.MessageBean>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -41,10 +44,19 @@ class MessageActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
loadingDialog = LoadingDialog(this).setMessage(getString(R.string.loading))
|
||||
binding.ivBack.setOnClickListener { finish() }
|
||||
binding.rvMessageList.layoutManager = LinearLayoutManager(this)
|
||||
binding.rvMessageList.adapter = messageAdapter
|
||||
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(object : PullRefreshLayout.OnRefreshListener {
|
||||
override fun onRefresh() {
|
||||
currentPage = 1
|
||||
hasMoreData = true
|
||||
loadMessageList()
|
||||
}
|
||||
})
|
||||
|
||||
binding.rvMessageList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
@@ -70,20 +82,21 @@ class MessageActivity : AppCompatActivity() {
|
||||
if (isLoading) return
|
||||
|
||||
isLoading = true
|
||||
|
||||
if (currentPage == 1) {
|
||||
showLoading()
|
||||
}
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val messageResponse = RetrofitNetwork.getNetworkService().getMessage(
|
||||
pageNum = currentPage,
|
||||
pageSize = pageSize
|
||||
)
|
||||
println("total: ${messageResponse.total}")
|
||||
println("rows size: ${messageResponse.rows.size}")
|
||||
println("当前页:$currentPage, 加载条数:${messageResponse.rows.size}")
|
||||
|
||||
val newMessages = messageResponse.rows
|
||||
val loadedCount = newMessages.size
|
||||
|
||||
if (loadedCount < pageSize) {
|
||||
if (newMessages.size < pageSize) {
|
||||
hasMoreData = false
|
||||
}
|
||||
|
||||
@@ -98,11 +111,11 @@ class MessageActivity : AppCompatActivity() {
|
||||
allMessages.clear()
|
||||
}
|
||||
allMessages.addAll(newMessages)
|
||||
lastLoadedCount = loadedCount
|
||||
|
||||
val items = convertToMessageListItems(allMessages)
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
hideLoading()
|
||||
hideEmptyState()
|
||||
messageAdapter.submitList(items)
|
||||
|
||||
@@ -116,20 +129,24 @@ class MessageActivity : AppCompatActivity() {
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
if (allMessages.isEmpty()) {
|
||||
println("items is empty, showing empty state")
|
||||
showEmptyState()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println("Exception: ${e.message}")
|
||||
e.printStackTrace()
|
||||
withContext(Dispatchers.Main) {
|
||||
if (allMessages.isEmpty()) {
|
||||
showEmptyState()
|
||||
noNetwork()
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
isLoading = false
|
||||
if (currentPage == 1) {
|
||||
withContext(Dispatchers.Main) {
|
||||
hideLoading()
|
||||
binding.swipeRefreshLayout.finishRefresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,17 +158,35 @@ class MessageActivity : AppCompatActivity() {
|
||||
loadMessageList()
|
||||
}
|
||||
|
||||
private fun showLoading() {
|
||||
binding.swipeRefreshLayout.visibility = View.GONE
|
||||
binding.emptyLayout.visibility = View.GONE
|
||||
binding.layoutNoNetwork.visibility = View.GONE
|
||||
loadingDialog.show()
|
||||
}
|
||||
|
||||
private fun hideLoading() {
|
||||
binding.swipeRefreshLayout.visibility = View.VISIBLE
|
||||
loadingDialog.dismiss()
|
||||
}
|
||||
|
||||
private fun showEmptyState() {
|
||||
binding.rvMessageList.visibility = View.GONE
|
||||
binding.swipeRefreshLayout.visibility = View.GONE
|
||||
binding.emptyLayout.visibility = View.VISIBLE
|
||||
binding.tvNoMoreData.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun hideEmptyState() {
|
||||
binding.rvMessageList.visibility = View.VISIBLE
|
||||
binding.swipeRefreshLayout.visibility = View.VISIBLE
|
||||
binding.emptyLayout.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun noNetwork() {
|
||||
binding.swipeRefreshLayout.visibility = View.GONE
|
||||
binding.layoutNoNetwork.visibility = View.VISIBLE
|
||||
binding.tvNoMoreData.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun showNoMoreDataHint() {
|
||||
binding.tvNoMoreData.visibility = View.VISIBLE
|
||||
}
|
||||
@@ -160,20 +195,17 @@ class MessageActivity : AppCompatActivity() {
|
||||
binding.tvNoMoreData.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun convertToMessageListItems(messages: List<com.example.defenseapplication.bean.MessageBean>): List<MessageListItem> {
|
||||
private fun convertToMessageListItems(messages: List<com.ckkj.defense_device.bean.MessageBean>): List<MessageListItem> {
|
||||
val items = mutableListOf<MessageListItem>()
|
||||
val groupedMessages = messages.groupBy { extractDate(it.createTime ?: "") }
|
||||
groupedMessages.forEach { (date, messageList) ->
|
||||
val headerTitle = formatDate(date)
|
||||
messageList.forEachIndexed { index, message ->
|
||||
println(" 消息${index + 1}: id=${message.id}, categoryName=${message.categoryName}, createTime=${message.createTime}")
|
||||
}
|
||||
items.add(MessageListItem.Header(headerTitle))
|
||||
messageList.forEach { message ->
|
||||
items.add(
|
||||
MessageListItem.Message(
|
||||
time = extractTime(message.createTime ?: ""),
|
||||
title = message.categoryName ?: "未知消息",
|
||||
title = message.categoryName ?: "",
|
||||
dateTime = message.createTime ?: "",
|
||||
unread = false
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.home
|
||||
package com.ckkj.defense_device.home
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
@@ -9,21 +9,23 @@ import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.bean.UserInfoBean
|
||||
import com.example.defenseapplication.databinding.PersonalFragmentBinding
|
||||
import com.example.defenseapplication.liveVideo.LinkedUserActivity
|
||||
import com.example.defenseapplication.personal.FaceManagementActivity
|
||||
import com.example.defenseapplication.personal.PasswordManagementActivity
|
||||
import com.example.defenseapplication.personal.PersonalProfileActivity
|
||||
import com.example.defenseapplication.utils.AppLanguage
|
||||
import com.example.defenseapplication.utils.LanguageUtil
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.utils.UserinfoUtil
|
||||
import com.example.defenseapplication.utils.ActivityManager
|
||||
import com.example.defenseapplication.view.FamilySwitchDialog
|
||||
import com.example.defenseapplication.view.LanguageDialog
|
||||
import com.example.defenseapplication.home.HomeActivity
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.bean.UserInfoBean
|
||||
import com.ckkj.defense_device.databinding.PersonalFragmentBinding
|
||||
import com.ckkj.defense_device.liveVideo.LinkedUserActivity
|
||||
import com.ckkj.defense_device.personal.FaceManagementActivity
|
||||
import com.ckkj.defense_device.personal.PasswordManagementActivity
|
||||
import com.ckkj.defense_device.personal.PersonalProfileActivity
|
||||
import com.ckkj.defense_device.personal.SettingsMenusActivity
|
||||
import com.ckkj.defense_device.utils.AppLanguage
|
||||
import com.ckkj.defense_device.utils.LanguageUtil
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.utils.UserinfoUtil
|
||||
import com.ckkj.defense_device.utils.ActivityManager
|
||||
import com.ckkj.defense_device.view.CustomDialogFragmentText
|
||||
import com.ckkj.defense_device.view.FamilySwitchDialog
|
||||
import com.ckkj.defense_device.view.LanguageDialog
|
||||
import com.ckkj.defense_device.view.LoadingDialog
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -34,6 +36,7 @@ class PersonalFragment : Fragment() {
|
||||
// ViewBinding
|
||||
private var _binding: PersonalFragmentBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private var loadingDialog: LoadingDialog? = null
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
fetchUserInfo()
|
||||
@@ -49,10 +52,10 @@ class PersonalFragment : Fragment() {
|
||||
.titleBar(binding.headerLayout)
|
||||
.init()
|
||||
Glide.with(this)
|
||||
.load(R.drawable.img)
|
||||
.load("")
|
||||
.circleCrop()
|
||||
.into(binding.ivAvatar)
|
||||
binding.headerLayout.setOnClickListener {
|
||||
binding.ivAvatar.setOnClickListener {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().getUserInfo()
|
||||
@@ -101,13 +104,20 @@ class PersonalFragment : Fragment() {
|
||||
}
|
||||
// 退出登录点击事件
|
||||
binding.btnLogout.setOnClickListener {
|
||||
val dialog = CustomDialogFragmentText()
|
||||
.setTitle(getString(R.string.tip))
|
||||
.setMessage(getString(R.string.logout_confirm))
|
||||
.setShowInput(false)
|
||||
.setNegativeText(getString(R.string.cancel))
|
||||
.setPositiveText(getString(R.string.confirm))
|
||||
.setOnConfirmListener {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().logout()
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200) {
|
||||
UserinfoUtil.clearUserInfo()
|
||||
val intent = Intent(requireContext(), com.example.defenseapplication.login.LoginActivity::class.java)
|
||||
val intent = Intent(requireContext(), com.ckkj.defense_device.login.LoginActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
requireActivity().finish()
|
||||
@@ -123,6 +133,12 @@ class PersonalFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
}
|
||||
dialog.show(childFragmentManager, "logout_dialog")
|
||||
}
|
||||
binding.ivMenu.setOnClickListener {
|
||||
val intent = Intent(requireContext(), SettingsMenusActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
fetchCurrentFamily()
|
||||
return binding.root
|
||||
}
|
||||
@@ -220,6 +236,7 @@ class PersonalFragment : Fragment() {
|
||||
|
||||
|
||||
private fun fetchUserInfo() {
|
||||
loadingDialog = LoadingDialog(requireContext()).setMessage(getString(R.string.loading)).apply { show() }
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().getUserInfo()
|
||||
@@ -230,6 +247,11 @@ class PersonalFragment : Fragment() {
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
withContext(Dispatchers.Main) {
|
||||
loadingDialog?.dismiss()
|
||||
loadingDialog = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,8 +265,8 @@ class PersonalFragment : Fragment() {
|
||||
}
|
||||
userInfo.avatar?.let {
|
||||
val requestOptions = RequestOptions()
|
||||
.placeholder(R.drawable.img) // 加载中显示
|
||||
.error(R.drawable.img) // 失败时显示
|
||||
.placeholder(R.mipmap.img) // 加载中显示
|
||||
.error(R.mipmap.img) // 失败时显示
|
||||
|
||||
Glide.with(this)
|
||||
.load(it) // 如果 avatar 为 null,Glide 会直接回调 error
|
||||
@@ -258,6 +280,7 @@ class PersonalFragment : Fragment() {
|
||||
} else {
|
||||
getString(R.string.member)
|
||||
}
|
||||
binding.tvRoleTag.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package com.example.defenseapplication.home
|
||||
package com.ckkj.defense_device.home
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.bean.AddDeviceBean
|
||||
import com.example.defenseapplication.bean.DeviceBean
|
||||
import com.example.defenseapplication.databinding.SetNameActivityBinding
|
||||
import com.example.defenseapplication.liveVideo.LiveVideoActivity
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.bean.AddDeviceBean
|
||||
import com.ckkj.defense_device.databinding.SetNameActivityBinding
|
||||
import com.ckkj.defense_device.liveVideo.LiveVideoActivity
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -61,7 +60,9 @@ class SetNameActivity : AppCompatActivity() {
|
||||
withContext(Dispatchers.Main) {
|
||||
if (result.code == 200) {
|
||||
Toast.makeText(this@SetNameActivity, "设备添加成功", Toast.LENGTH_SHORT).show()
|
||||
startActivity(Intent(this@SetNameActivity, LiveVideoActivity::class.java))
|
||||
startActivity(Intent(this@SetNameActivity, HomeActivity::class.java).apply {
|
||||
putExtra(HomeActivity.EXTRA_REFRESH, true)
|
||||
})
|
||||
finish()
|
||||
} else {
|
||||
Toast.makeText(this@SetNameActivity, result.msg ?: "添加失败", Toast.LENGTH_SHORT).show()
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.ckkj.defense_device.home
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.ckkj.defense_device.databinding.ActivityStartBinding
|
||||
import com.ckkj.defense_device.login.LoginActivity
|
||||
import com.ckkj.defense_device.utils.ApiConfig
|
||||
import com.ckkj.defense_device.utils.UserinfoUtil
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
|
||||
class StartActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityStartBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityStartBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
ImmersionBar.with(this)
|
||||
.statusBarDarkFont(true)
|
||||
.titleBar(null)
|
||||
.init()
|
||||
|
||||
// 延迟2秒后再判断登录状态
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
val userInfo = UserinfoUtil.getUserInfo()
|
||||
if (userInfo != null) {
|
||||
// 设置token
|
||||
ApiConfig.authToken = userInfo.access_token
|
||||
val intent = Intent(this, HomeActivity::class.java)
|
||||
startActivity(intent)
|
||||
} else {
|
||||
val intent = Intent(this, LoginActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
finish()
|
||||
}, 2000) // 2秒延迟
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,22 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.adapter.AddLinkedUserAdapter
|
||||
import com.example.defenseapplication.adapter.UserItem
|
||||
import com.example.defenseapplication.bean.AddDeviceUserRequest
|
||||
import com.example.defenseapplication.bean.FamilyMembersBean
|
||||
import com.example.defenseapplication.databinding.AddLinkedUserActivityBinding
|
||||
import com.example.defenseapplication.utils.DeviceIdEvent
|
||||
import com.example.defenseapplication.utils.DeviceUserUpdateEvent
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.adapter.AddLinkedUserAdapter
|
||||
import com.ckkj.defense_device.adapter.UserItem
|
||||
import com.ckkj.defense_device.bean.AddDeviceUserRequest
|
||||
import com.ckkj.defense_device.bean.FamilyMembersBean
|
||||
import com.ckkj.defense_device.databinding.AddLinkedUserActivityBinding
|
||||
import com.ckkj.defense_device.utils.DeviceIdEvent
|
||||
import com.ckkj.defense_device.utils.DeviceUserUpdateEvent
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -95,19 +96,33 @@ class AddLinkedUserActivity : AppCompatActivity() {
|
||||
Toast.makeText(this@AddLinkedUserActivity, "暂无家庭成员数据", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} else {
|
||||
hide()
|
||||
Toast.makeText(this@AddLinkedUserActivity, "请求失败: ${response.msg}", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("AddLinkedUserActivity", "网络请求异常", e)
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.swipeRefresh.isRefreshing = false
|
||||
noNetwork()
|
||||
Toast.makeText(this@AddLinkedUserActivity, "网络请求失败: ${e.message}", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hide() {
|
||||
binding.searchLayout.visibility = View.GONE
|
||||
binding.rvAddLinkedUser.visibility = View.GONE
|
||||
binding.butting?.visibility = View.GONE
|
||||
binding.layoutNoPermission?.visibility = View.VISIBLE
|
||||
}
|
||||
private fun noNetwork() {
|
||||
binding.searchLayout.visibility = View.GONE
|
||||
binding.rvAddLinkedUser.visibility = View.GONE
|
||||
binding.butting?.visibility = View.GONE
|
||||
binding.layoutNoNetwork?.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun updateFamilyMemberList(familyMembersList: List<FamilyMembersBean>) {
|
||||
fullUserItemList.clear()
|
||||
familyMembersList.forEach { member ->
|
||||
@@ -0,0 +1,428 @@
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.media.AudioManager
|
||||
import android.media.MediaScannerConnection
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.adapter.AlarmLogAdapter
|
||||
import com.ckkj.defense_device.bean.DeviceAlarmBean
|
||||
import com.ckkj.defense_device.databinding.AlarmLogActivityBinding
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
|
||||
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
|
||||
import com.shuyu.gsyvideoplayer.utils.OrientationUtils
|
||||
import com.bigkoo.pickerview.builder.TimePickerBuilder
|
||||
import com.bigkoo.pickerview.listener.OnTimeSelectListener
|
||||
import com.ckkj.defense_device.view.CustomDialogFragment
|
||||
import com.ckkj.defense_device.view.LoadingDialog
|
||||
import com.ckkj.defense_device.view.MyGSYVideoPlayer
|
||||
import com.ckkj.defense_device.view.showDefenseDialog
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import android.net.Uri
|
||||
import com.chiclaim.android.downloader.DownloadRequest
|
||||
import com.chiclaim.android.downloader.DownloadListener
|
||||
|
||||
//告警记录
|
||||
class AlarmLogActivity : AppCompatActivity() {
|
||||
private lateinit var binding: AlarmLogActivityBinding
|
||||
private lateinit var calendar: Calendar
|
||||
private var adapter: AlarmLogAdapter? = null
|
||||
private val alarmList = mutableListOf<DeviceAlarmBean>()
|
||||
private val originalAlarmList = mutableListOf<DeviceAlarmBean>()
|
||||
private var deviceId: String? = null
|
||||
private var isLoading = false
|
||||
private var videoUrl: String? = null
|
||||
private var orientationUtils: OrientationUtils? = null
|
||||
|
||||
private var isMute = false
|
||||
private lateinit var audioManager: AudioManager
|
||||
private var currentAlarmItem: DeviceAlarmBean? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = AlarmLogActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
ImmersionBar.with(this)
|
||||
.statusBarDarkFont(true)
|
||||
.titleBar(null)
|
||||
.init()
|
||||
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
|
||||
deviceId = intent.getStringExtra("device_id")
|
||||
videoUrl = intent.getStringExtra("video_url")
|
||||
calendar = Calendar.getInstance()
|
||||
updateDateDisplay()
|
||||
initVideoPlayer()
|
||||
initRecyclerView()
|
||||
fetchAlarmList()
|
||||
initListener()
|
||||
}
|
||||
|
||||
private fun initVideoPlayer() {
|
||||
val videoUrl = intent.getStringExtra("video_url") ?: "https://media.w3.org/2010/05/sintel/trailer.mp4"
|
||||
val progressDrawable = ContextCompat.getDrawable(this, R.drawable.progress_video)
|
||||
val thumbDrawable = ContextCompat.getDrawable(this, R.drawable.thumb_video)
|
||||
|
||||
orientationUtils = OrientationUtils(this, binding.exoPlayContextId)
|
||||
orientationUtils?.isEnable = true
|
||||
|
||||
GSYVideoOptionBuilder()
|
||||
.setUrl(videoUrl)
|
||||
.setVideoTitle("")
|
||||
.setNeedLockFull(true)
|
||||
.setCacheWithPlay(false)
|
||||
.setRotateViewAuto(true)
|
||||
.setLockLand(false)
|
||||
.setShowFullAnimation(true)
|
||||
.setNeedShowWifiTip(false)
|
||||
.setEnlargeImageRes(R.mipmap.full_size)
|
||||
.setShrinkImageRes(R.mipmap.full_screen)
|
||||
.setBottomShowProgressBarDrawable(progressDrawable, thumbDrawable)
|
||||
.setVideoAllCallBack(object : GSYSampleCallBack() {
|
||||
override fun onPrepared(url: String?, vararg objects: Any?) {
|
||||
super.onPrepared(url, *objects)
|
||||
orientationUtils?.isEnable = true
|
||||
}
|
||||
|
||||
override fun onQuitFullscreen(url: String?, vararg objects: Any?) {
|
||||
super.onQuitFullscreen(url, *objects)
|
||||
orientationUtils?.backToProtVideo()
|
||||
}
|
||||
})
|
||||
.build(binding.exoPlayContextId)
|
||||
binding.exoPlayContextId.backButton.setOnClickListener {
|
||||
|
||||
if (orientationUtils?.isLand == 1) {
|
||||
// 当前全屏,先退出全屏
|
||||
binding.exoPlayContextId.fullscreenButton.performClick()
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
binding.exoPlayContextId.onControlVisibilityChanged = { show ->
|
||||
Log.e("GSY_TEST", "Activity收到回调 show=$show")
|
||||
val visible = if (show) View.VISIBLE else View.GONE
|
||||
|
||||
binding.ivDownload.visibility = visible
|
||||
binding.ivDelete.visibility = visible
|
||||
binding.ivMute.visibility = visible
|
||||
}
|
||||
|
||||
binding.exoPlayContextId.startPlayLogic()
|
||||
binding.exoPlayContextId.fullscreenButton.setOnClickListener {
|
||||
orientationUtils?.resolveByClick()
|
||||
|
||||
binding.exoPlayContextId.startWindowFullscreen(this, true, true)?.let { fullPlayer ->
|
||||
|
||||
if (fullPlayer is MyGSYVideoPlayer) {
|
||||
fullPlayer.onControlVisibilityChanged = { show ->
|
||||
val visible = if (show) View.VISIBLE else View.GONE
|
||||
binding.ivDownload.visibility = visible
|
||||
binding.ivDelete.visibility = visible
|
||||
binding.ivMute.visibility = visible
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
private fun initRecyclerView() {
|
||||
adapter = AlarmLogAdapter(alarmList) { item ->
|
||||
currentAlarmItem = item
|
||||
if (!item.video.isNullOrEmpty()) {
|
||||
binding.exoPlayContextId.setUp(item.video, true, item.categoryName)
|
||||
binding.exoPlayContextId.startPlayLogic()
|
||||
} else {
|
||||
Toast.makeText(this, "该告警记录没有视频", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
binding.alarmListRecyclerView.layoutManager = LinearLayoutManager(this)
|
||||
binding.alarmListRecyclerView.adapter = adapter
|
||||
}
|
||||
|
||||
private fun fetchAlarmList() {
|
||||
val currentDeviceId = deviceId ?: return
|
||||
isLoading = true
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().getDeviceAlarmList(
|
||||
deviceId = currentDeviceId,
|
||||
pageNum = "1",
|
||||
pageSize = "10"
|
||||
)
|
||||
Log.d("AlarmLogActivity", "总条数: ${response.total}, 当前页数据条数: ${response.rows.size}")
|
||||
val newData = response.rows
|
||||
originalAlarmList.clear()
|
||||
originalAlarmList.addAll(newData)
|
||||
filterAlarmListByDate(calendar)
|
||||
currentAlarmItem = alarmList.firstOrNull()
|
||||
Log.d("AlarmLogActivity", "已获取 ${newData.size} 条数据")
|
||||
} catch (e: Exception) {
|
||||
Log.e("AlarmLogActivity", "请求异常: ${e.message}", e)
|
||||
showAlarmListNetworkError()
|
||||
} finally {
|
||||
isLoading = false
|
||||
Log.d("AlarmLogActivity", "请求结束")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateAlarmListState() {
|
||||
if (alarmList.isEmpty()) {
|
||||
binding.alarmListRecyclerView.visibility = View.GONE
|
||||
binding.layoutNoPermission.visibility = View.VISIBLE
|
||||
binding.layoutNoNetwork.visibility = View.GONE
|
||||
} else {
|
||||
binding.alarmListRecyclerView.visibility = View.VISIBLE
|
||||
binding.layoutNoPermission.visibility = View.GONE
|
||||
binding.layoutNoNetwork.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun showAlarmListNetworkError() {
|
||||
binding.alarmListRecyclerView.visibility = View.GONE
|
||||
binding.layoutNoPermission.visibility = View.GONE
|
||||
binding.layoutNoNetwork.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun filterAlarmListByDate(selectedDate: Calendar) {
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
|
||||
val selectedDateStr = dateFormat.format(selectedDate.time)
|
||||
|
||||
alarmList.clear()
|
||||
originalAlarmList.forEach { item ->
|
||||
val itemDateStr = item.createTime.substring(0, 10)
|
||||
if (itemDateStr == selectedDateStr) {
|
||||
alarmList.add(item)
|
||||
}
|
||||
}
|
||||
adapter?.notifyDataSetChanged()
|
||||
Log.d("AlarmLogActivity", "日期筛选完成,筛选后条数: ${alarmList.size}")
|
||||
|
||||
if (alarmList.isEmpty()) {
|
||||
currentAlarmItem = null
|
||||
} else {
|
||||
currentAlarmItem = alarmList.firstOrNull()
|
||||
}
|
||||
updateAlarmListState()
|
||||
}
|
||||
|
||||
private fun updateDateDisplay() {
|
||||
val month = calendar.get(Calendar.MONTH) + 1
|
||||
val day = calendar.get(Calendar.DAY_OF_MONTH)
|
||||
binding.tvDate.text = "${month}月${day}日"
|
||||
}
|
||||
|
||||
private fun initListener() {
|
||||
|
||||
binding.expandImg.setOnClickListener {
|
||||
showDatePicker()
|
||||
}
|
||||
|
||||
binding.ivDownload.setOnClickListener {
|
||||
|
||||
// val item = currentAlarmItem
|
||||
//
|
||||
// if (item?.video.isNullOrEmpty()) {
|
||||
// Toast.makeText(
|
||||
// this,
|
||||
// "没有可下载的视频",
|
||||
// Toast.LENGTH_SHORT
|
||||
// ).show()
|
||||
// return@setOnClickListener
|
||||
// }
|
||||
|
||||
showConfirmDialog(
|
||||
getString(R.string.tip),
|
||||
getString(R.string.download_alarm_video_confirm)
|
||||
) {
|
||||
|
||||
//downloadVideo(item!!.video)
|
||||
downloadVideo(
|
||||
"https://media.w3.org/2010/05/sintel/trailer.mp4"
|
||||
)
|
||||
|
||||
Toast.makeText(
|
||||
this,
|
||||
getString(R.string.download_start),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
binding.ivDelete.setOnClickListener {
|
||||
val item = currentAlarmItem
|
||||
if (item == null) {
|
||||
Toast.makeText(this, "没有可删除的告警记录", Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
showConfirmDialog(getString(R.string.tip), getString(R.string.delete_alarm_video_confirm)) {
|
||||
val loadingDialog = LoadingDialog(this).setMessage("删除中...").apply { show() }
|
||||
deleteAlarmItem(item.id, loadingDialog)
|
||||
}
|
||||
}
|
||||
binding.ivMute.setOnClickListener {
|
||||
isMute = !isMute
|
||||
if (isMute) {
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0)
|
||||
binding.ivMute.setImageResource(
|
||||
R.mipmap.mute
|
||||
)
|
||||
} else {
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) / 2, 0)
|
||||
binding.ivMute.setImageResource(
|
||||
R.mipmap.un_mute
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun showDatePicker() {
|
||||
val timePicker = TimePickerBuilder(this, OnTimeSelectListener { date, _ ->
|
||||
calendar.time = date
|
||||
updateDateDisplay()
|
||||
filterAlarmListByDate(calendar)
|
||||
})
|
||||
.setType(booleanArrayOf(true, true, true, false, false, false)) // 年月日
|
||||
.setTitleText(getString(R.string.select_date))
|
||||
.setSubmitColor(Color.parseColor("#09C2BD"))//确定按钮文字颜色
|
||||
.setCancelColor(Color.parseColor("#09C2BD"))//取消按钮文字颜色
|
||||
.setSubCalSize(18)//确定和取消文字大小
|
||||
.setTextColorCenter(Color.parseColor("#09C2BD"))//选中颜色
|
||||
.setLineSpacingMultiplier(2.5f)//行间距倍数
|
||||
.setItemVisibleCount(5)//可见项数量
|
||||
.setDate(calendar) // 设置默认选中日期为tvDate显示的日期
|
||||
.build()
|
||||
timePicker.show()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
binding.exoPlayContextId.onVideoPause()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.exoPlayContextId.onVideoResume()
|
||||
}
|
||||
|
||||
private fun showConfirmDialog(title: String, message: String, onConfirm: () -> Unit) {
|
||||
val config = CustomDialogFragment.Config(
|
||||
title = title,
|
||||
message = message,
|
||||
positiveText = getString(R.string.confirm),
|
||||
negativeText = getString(R.string.cancel)
|
||||
)
|
||||
showDefenseDialog(config, onPositiveClick = { onConfirm() })
|
||||
}
|
||||
|
||||
private fun downloadVideo(url: String) {
|
||||
|
||||
val dir = File(
|
||||
Environment.getExternalStoragePublicDirectory(
|
||||
Environment.DIRECTORY_MOVIES
|
||||
),
|
||||
"AlarmVideo"
|
||||
)
|
||||
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs()
|
||||
}
|
||||
|
||||
val targetFile = File(
|
||||
dir,
|
||||
"${System.currentTimeMillis()}.mp4"
|
||||
)
|
||||
|
||||
val request = DownloadRequest(
|
||||
this,
|
||||
url
|
||||
)
|
||||
.setDestinationUri(Uri.fromFile(targetFile))
|
||||
.setNotificationTitle("${"视频名称"}:视频下载")
|
||||
.registerListener(object : DownloadListener {
|
||||
|
||||
override fun onDownloadStart() {
|
||||
Log.d("DOWNLOAD", "开始下载")
|
||||
}
|
||||
|
||||
override fun onProgressUpdate(percent: Int) {
|
||||
Log.d("DOWNLOAD", "进度:$percent%")
|
||||
}
|
||||
override fun onDownloadComplete(uri: Uri) {
|
||||
MediaScannerConnection.scanFile(
|
||||
this@AlarmLogActivity,
|
||||
arrayOf(targetFile.absolutePath),
|
||||
arrayOf("video/mp4"),
|
||||
null
|
||||
)
|
||||
|
||||
runOnUiThread {
|
||||
ToastUtils.showSuccess(
|
||||
this@AlarmLogActivity,
|
||||
"下载成功"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDownloadFailed(e: Throwable) {
|
||||
runOnUiThread {
|
||||
ToastUtils.showError(
|
||||
this@AlarmLogActivity,
|
||||
"下载失败:${e.message}"
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
request.startDownload()
|
||||
}
|
||||
|
||||
private fun deleteAlarmItem(id: String, loadingDialog: LoadingDialog) {
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().deleteMessage(id)
|
||||
if (response.code == 200) {
|
||||
Toast.makeText(this@AlarmLogActivity, getString(R.string.delete_success), Toast.LENGTH_SHORT).show()
|
||||
originalAlarmList.removeAll { it.id == id }
|
||||
alarmList.removeAll { it.id == id }
|
||||
adapter?.notifyDataSetChanged()
|
||||
currentAlarmItem = alarmList.firstOrNull()
|
||||
if (alarmList.isEmpty()) {
|
||||
showAlarmListNetworkError()
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this@AlarmLogActivity, response.msg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(this@AlarmLogActivity, "删除失败: ${e.message}", Toast.LENGTH_SHORT).show()
|
||||
} finally {
|
||||
loadingDialog.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
orientationUtils?.releaseListener()
|
||||
binding.exoPlayContextId.release()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
@@ -8,12 +8,12 @@ import java.util.Calendar
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.AutoModeActivityBinding
|
||||
import com.example.defenseapplication.utils.DeviceIdEvent
|
||||
import com.example.defenseapplication.utils.DeviceUpdateEvent
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.view.AutoModeNoticeDialog
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.databinding.AutoModeActivityBinding
|
||||
import com.ckkj.defense_device.utils.DeviceIdEvent
|
||||
import com.ckkj.defense_device.utils.DeviceUpdateEvent
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.AutoModeNoticeDialog
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -31,6 +31,7 @@ class AutoModeActivity : AppCompatActivity() {
|
||||
private var selectedStartMinute = 0
|
||||
private var selectedEndHour = 10
|
||||
private var selectedEndMinute = 0
|
||||
private var optionPassword: String? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -42,6 +43,8 @@ class AutoModeActivity : AppCompatActivity() {
|
||||
.titleBar(binding.topBar)
|
||||
.init()
|
||||
|
||||
optionPassword = intent.getStringExtra("optionPassword")
|
||||
|
||||
initListener()
|
||||
|
||||
loadCurrentSettings()
|
||||
@@ -173,11 +176,12 @@ class AutoModeActivity : AppCompatActivity() {
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val deviceBean = com.example.defenseapplication.bean.DeviceBean(
|
||||
val deviceBean = com.ckkj.defense_device.bean.DeviceBean(
|
||||
id = deviceId,
|
||||
workMode = selectedMode,
|
||||
startTime = startTime,
|
||||
endTime = endTime
|
||||
endTime = endTime,
|
||||
optionPassword = optionPassword
|
||||
)
|
||||
val response = RetrofitNetwork.getNetworkService().updateDeviceInfo(deviceBean)
|
||||
withContext(Dispatchers.Main) {
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.databinding.DeviceInfoActivityBinding
|
||||
import com.example.defenseapplication.utils.DeviceIdEvent
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.databinding.DeviceInfoActivityBinding
|
||||
import com.ckkj.defense_device.utils.DeviceIdEvent
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -55,9 +54,9 @@ class DeviceInfoActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateDeviceInfo(device: com.example.defenseapplication.bean.DeviceBean) {
|
||||
binding.tvDeviceModelValue.text = device.deviceNo.toString()
|
||||
binding.tvDeviceNoValue.text = device.deviceSn.toString()
|
||||
binding.tvFwVersionValue.text = device.fwVer.toString()
|
||||
private fun updateDeviceInfo(device: com.ckkj.defense_device.bean.DeviceBean) {
|
||||
binding.tvDeviceModelValue.text = device.deviceNo?.toString()?: ""
|
||||
binding.tvDeviceNoValue.text = device.deviceSn?.toString() ?: ""
|
||||
binding.tvFwVersionValue.text = device.fwVer?.toString()?: ""
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
@@ -11,22 +11,22 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.adapter.LinkedUser
|
||||
import com.example.defenseapplication.adapter.LinkedUserAdapter
|
||||
import com.example.defenseapplication.bean.DeleteDeviceUserRequest
|
||||
import com.example.defenseapplication.bean.DeviceUserBean
|
||||
import com.example.defenseapplication.bean.FamilyMembersBean
|
||||
import com.example.defenseapplication.bean.VerifyOptionPasswordRequest
|
||||
import com.example.defenseapplication.databinding.LinkedUserActivityBinding
|
||||
import com.example.defenseapplication.personal.PasswordInputDialog
|
||||
import com.example.defenseapplication.utils.DeviceIdEvent
|
||||
import com.example.defenseapplication.utils.DeviceUserUpdateEvent
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.view.CustomDialogFragmentText
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.adapter.LinkedUser
|
||||
import com.ckkj.defense_device.adapter.LinkedUserAdapter
|
||||
import com.ckkj.defense_device.bean.DeleteDeviceUserRequest
|
||||
import com.ckkj.defense_device.bean.DeviceUserBean
|
||||
import com.ckkj.defense_device.bean.FamilyMembersBean
|
||||
import com.ckkj.defense_device.bean.VerifyOptionPasswordRequest
|
||||
import com.ckkj.defense_device.databinding.LinkedUserActivityBinding
|
||||
import com.ckkj.defense_device.personal.PasswordInputDialog
|
||||
import com.ckkj.defense_device.utils.DeviceIdEvent
|
||||
import com.ckkj.defense_device.utils.DeviceUserUpdateEvent
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.CustomDialogFragmentText
|
||||
import com.ckkj.defense_device.view.PullRefreshLayout
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.yanzhenjie.recyclerview.SwipeMenuItem
|
||||
import com.yanzhenjie.recyclerview.SwipeRecyclerView
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -96,9 +96,11 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
|
||||
(binding.rvLinkedUser as RecyclerView).layoutManager = LinearLayoutManager(this)
|
||||
|
||||
binding.swipeRefresh.setOnRefreshListener {
|
||||
binding.swipeRefresh.setOnRefreshListener(object : PullRefreshLayout.OnRefreshListener {
|
||||
override fun onRefresh() {
|
||||
fetchUserList()
|
||||
}
|
||||
})
|
||||
|
||||
binding.rvLinkedUser.setSwipeMenuCreator { leftMenu, rightMenu, position ->
|
||||
if (mode == MODE_SETTINGS) {
|
||||
@@ -230,7 +232,6 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun fetchUserList() {
|
||||
binding.swipeRefresh.isRefreshing = true
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
var deviceId: String? = null
|
||||
@@ -239,7 +240,7 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
if (deviceId.isNullOrEmpty()) {
|
||||
Toast.makeText(this@LinkedUserActivity, "设备 ID 为空", Toast.LENGTH_SHORT).show()
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.swipeRefresh.isRefreshing = false
|
||||
binding.swipeRefresh.finishRefresh()
|
||||
}
|
||||
return@launch
|
||||
}
|
||||
@@ -250,7 +251,7 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
RetrofitNetwork.getNetworkService().getFamilyMembers()
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.swipeRefresh.isRefreshing = false
|
||||
binding.swipeRefresh.finishRefresh()
|
||||
if (response.code == 200 && response.data != null) {
|
||||
if (mode == MODE_SETTINGS) {
|
||||
updateDeviceUserList(response.data as List<DeviceUserBean>)
|
||||
@@ -258,18 +259,32 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
updateFamilyMembersList(response.data as List<FamilyMembersBean>)
|
||||
}
|
||||
} else {
|
||||
hide()
|
||||
Toast.makeText(this@LinkedUserActivity, response.msg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.swipeRefresh.isRefreshing = false
|
||||
Toast.makeText(this@LinkedUserActivity, "网络请求失败", Toast.LENGTH_SHORT).show()
|
||||
binding.swipeRefresh.finishRefresh()
|
||||
noNetwork()
|
||||
Toast.makeText(this@LinkedUserActivity, R.string.network_request_failed, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun hide() {
|
||||
binding.searchLayout.visibility = View.GONE
|
||||
binding.rvLinkedUser.visibility = View.GONE
|
||||
binding.butting?.visibility = View.GONE
|
||||
binding.layoutNoPermission?.visibility = View.VISIBLE
|
||||
}
|
||||
private fun noNetwork() {
|
||||
binding.searchLayout.visibility = View.GONE
|
||||
binding.rvLinkedUser.visibility = View.GONE
|
||||
binding.butting?.visibility = View.GONE
|
||||
binding.layoutNoNetwork?.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun updateDeviceUserList(deviceUserList: List<DeviceUserBean>) {
|
||||
fullUserList.clear()
|
||||
@@ -339,7 +354,7 @@ class LinkedUserActivity : AppCompatActivity() {
|
||||
|
||||
binding.fabAdd.setOnClickListener {
|
||||
if (checkUserLimit()) {
|
||||
val intent = Intent(this, com.example.defenseapplication.personal.InvitationCodeActivity::class.java)
|
||||
val intent = Intent(this, com.ckkj.defense_device.personal.InvitationCodeActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,484 @@
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.adapter.AlarmLogHorizontalAdapter
|
||||
import com.ckkj.defense_device.base.BaseActivity
|
||||
import com.ckkj.defense_device.bean.DeviceAlarmBean
|
||||
import com.ckkj.defense_device.databinding.LiveVideoActivityBinding
|
||||
import com.ckkj.defense_device.utils.ActivityManager
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
|
||||
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
|
||||
import com.shuyu.gsyvideoplayer.utils.OrientationUtils
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.ckkj.defense_device.bean.VideoStreamInfo
|
||||
import com.ckkj.defense_device.bean.VideoStreamRequest
|
||||
import com.ckkj.defense_device.view.MyGSYVideoPlayerLive
|
||||
|
||||
class LiveVideoActivity : BaseActivity() {
|
||||
private lateinit var binding: LiveVideoActivityBinding
|
||||
|
||||
private var isVoiceEnabled = false
|
||||
private var isLightOn = false
|
||||
private var isConsoleVisible = false
|
||||
private var deviceId: String? = null
|
||||
private var deviceNo: String? = null
|
||||
private var alarmList: MutableList<DeviceAlarmBean> = mutableListOf()
|
||||
private var alarmAdapter: AlarmLogHorizontalAdapter? = null
|
||||
private var currentPage = 1
|
||||
private var totalPage = 1
|
||||
private val pageSize = 10
|
||||
private var hasMore = true
|
||||
private var isLoading = false
|
||||
|
||||
private var orientationUtils: OrientationUtils? = null
|
||||
private val ptzHandler = Handler(Looper.getMainLooper())
|
||||
private var currentPtzDirection: String? = null
|
||||
private var streamUrl: String? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Log.d("onEnterFullscreen", "onCreate")
|
||||
|
||||
binding = LiveVideoActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
ImmersionBar.with(this)
|
||||
.statusBarDarkFont(true)
|
||||
.titleBar(binding.topBar)
|
||||
.init()
|
||||
|
||||
deviceId = intent.getStringExtra("device_id")
|
||||
val deviceName = intent.getStringExtra("device_name")
|
||||
deviceNo = intent.getStringExtra("deviceNo")
|
||||
val light = intent.getStringExtra("light")
|
||||
if (!deviceName.isNullOrEmpty()) {
|
||||
binding.tvTitle.text = deviceName
|
||||
}
|
||||
|
||||
initVideoPlayer()
|
||||
initAlarmRecyclerView()
|
||||
initListener()
|
||||
fetchAlarmList()
|
||||
}
|
||||
|
||||
/*
|
||||
* 这段代码重写了onConfigurationChanged方法,用于监听屏幕方向变化:
|
||||
当屏幕旋转为横屏时,隐藏顶部栏(topBar)
|
||||
当屏幕为竖屏时,显示顶部栏
|
||||
目的是在横屏观看视频时提供更沉浸的全屏体验。
|
||||
* */
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
binding.topBar.visibility = View.GONE
|
||||
} else {
|
||||
binding.topBar.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
private fun initVideoPlayer() {
|
||||
orientationUtils = OrientationUtils(this, binding.exoPlayContextId)
|
||||
orientationUtils?.isEnable = true
|
||||
|
||||
hidePlayerControls()
|
||||
fetchStreamUrl()
|
||||
}
|
||||
|
||||
private fun fetchStreamUrl() {
|
||||
val no = deviceNo ?: return
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().videoStart(VideoStreamRequest(no))
|
||||
Log.d("直播流开始", "code=${response.code}, msg=${response.msg}")
|
||||
if (response.code == 200 && response.data != null) {
|
||||
//flv(http) 支持(IjkPlayer最好)
|
||||
//hls(.m3u8) 支持(ExoPlayer/Ijk都支持)
|
||||
//rtmp IjkPlayer支持,Exo默认不支持
|
||||
//rtsp IjkPlayer支持
|
||||
//webrtcGSYVideoPlayer 不支持
|
||||
streamUrl = response.data.playUrls.flv
|
||||
Log.d("直播流开始", "获取地址:$streamUrl")
|
||||
setupVideoPlayer(streamUrl!!)
|
||||
} else {
|
||||
Log.e("直播流开始", response.msg)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("直播流开始", "异常", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupVideoPlayer(videoUrl: String) {
|
||||
GSYVideoOptionBuilder()
|
||||
.setUrl(videoUrl)
|
||||
.setCacheWithPlay(false)
|
||||
.setRotateViewAuto(true)
|
||||
.setLockLand(false)
|
||||
.setShowFullAnimation(true)
|
||||
.setNeedShowWifiTip(false)
|
||||
.setEnlargeImageRes(R.drawable.full_size)
|
||||
.setShrinkImageRes(R.drawable.full_screen)
|
||||
.setVideoAllCallBack(object : GSYSampleCallBack() {
|
||||
override fun onPrepared(url: String?, vararg objects: Any?) {
|
||||
super.onPrepared(url, *objects)
|
||||
orientationUtils?.isEnable = true
|
||||
}
|
||||
|
||||
override fun onQuitFullscreen(url: String?, vararg objects: Any?) {
|
||||
super.onQuitFullscreen(url, *objects)
|
||||
orientationUtils?.backToProtVideo()
|
||||
}
|
||||
|
||||
})
|
||||
.build(binding.exoPlayContextId)
|
||||
binding.exoPlayContextId.startPlayLogic()
|
||||
binding.exoPlayContextId.fullscreenButton.setOnClickListener {
|
||||
binding.exoPlayContextId.onPtzControlListener =
|
||||
object : MyGSYVideoPlayerLive.OnPtzControlListener {
|
||||
override fun onStartPtz(direction: String) {
|
||||
val no = deviceNo ?: return
|
||||
startPtz(deviceNo = no, direction = direction)
|
||||
}
|
||||
|
||||
override fun onStopPtz() {
|
||||
stopCurrentPtz()
|
||||
}
|
||||
|
||||
override fun onShoot() {
|
||||
deviceNo?.let { shoot(it) }
|
||||
}
|
||||
}
|
||||
orientationUtils?.resolveByClick()
|
||||
binding.exoPlayContextId.startWindowFullscreen(this, true, true)
|
||||
}
|
||||
}
|
||||
private fun hidePlayerControls() {
|
||||
binding.exoPlayContextId.backButton.visibility = View.GONE
|
||||
binding.exoPlayContextId.titleTextView.visibility = View.GONE
|
||||
binding.exoPlayContextId.startButton.visibility = View.GONE
|
||||
|
||||
binding.exoPlayContextId.findViewById<View>(
|
||||
com.shuyu.gsyvideoplayer.R.id.current
|
||||
)?.visibility = View.GONE
|
||||
|
||||
binding.exoPlayContextId.findViewById<View>(
|
||||
com.shuyu.gsyvideoplayer.R.id.total
|
||||
)?.visibility = View.GONE
|
||||
|
||||
binding.exoPlayContextId.findViewById<View>(
|
||||
com.shuyu.gsyvideoplayer.R.id.progress
|
||||
)?.visibility = View.INVISIBLE
|
||||
|
||||
binding.exoPlayContextId.findViewById<View>(
|
||||
com.shuyu.gsyvideoplayer.R.id.start
|
||||
)?.visibility = View.GONE
|
||||
|
||||
binding.exoPlayContextId.findViewById<View>(
|
||||
com.shuyu.gsyvideoplayer.R.id.layout_bottom
|
||||
)?.setBackgroundColor(Color.TRANSPARENT)
|
||||
|
||||
}
|
||||
|
||||
private fun initAlarmRecyclerView() {
|
||||
val layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
|
||||
binding.alarmLogRecyclerView.layoutManager = layoutManager
|
||||
alarmAdapter = AlarmLogHorizontalAdapter(alarmList) { messageBean ->
|
||||
val intent = Intent(this, AlarmLogActivity::class.java)
|
||||
intent.putExtra("device_id", deviceId)
|
||||
intent.putExtra("selected_id", messageBean.id)
|
||||
intent.putExtra("video_url", messageBean.video)
|
||||
intent.putExtra("create_time", messageBean.createTime)
|
||||
intent.putExtra("from_live_video", true)
|
||||
startActivity(intent)
|
||||
}
|
||||
binding.alarmLogRecyclerView.adapter = alarmAdapter
|
||||
|
||||
binding.alarmLogRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
if (dx > 0 && !isLoading && hasMore) {
|
||||
val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
|
||||
if (lastVisibleItemPosition == alarmList.size - 1) {
|
||||
loadMoreAlarms()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun loadMoreAlarms() {
|
||||
if (!hasMore || isLoading) return
|
||||
currentPage++
|
||||
if (currentPage > totalPage) {
|
||||
hasMore = false
|
||||
return
|
||||
}
|
||||
fetchAlarmList(currentPage)
|
||||
}
|
||||
|
||||
private fun initListener() {
|
||||
binding.btnBack.setOnClickListener {
|
||||
ActivityManager.finishExceptHome()
|
||||
val intent = Intent(this, com.ckkj.defense_device.home.HomeActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
binding.ivMenu.setOnClickListener {
|
||||
val intent = Intent(this, SettingsActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
|
||||
binding.llLight.setOnClickListener {
|
||||
isLightOn = !isLightOn
|
||||
|
||||
if (isLightOn) {
|
||||
binding.ivLight.setImageResource(com.ckkj.defense_device.R.mipmap.light_on_open)
|
||||
} else {
|
||||
binding.ivLight.setImageResource(com.ckkj.defense_device.R.mipmap.light_on)
|
||||
}
|
||||
}
|
||||
|
||||
binding.xq.setOnClickListener {
|
||||
val intent = Intent(this, AlarmLogActivity::class.java)
|
||||
intent.putExtra("device_id", deviceId)
|
||||
intent.putExtra("from_live_video", true)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
binding.llRecord.setOnClickListener {
|
||||
isConsoleVisible = !isConsoleVisible
|
||||
if (isConsoleVisible) {
|
||||
binding.llAlarmLog.visibility = View.GONE
|
||||
binding.consoleBar.visibility = View.VISIBLE
|
||||
binding.ivRecord.setImageResource(R.mipmap.copy_open)
|
||||
} else {
|
||||
binding.llAlarmLog.visibility = View.VISIBLE
|
||||
binding.consoleBar.visibility = View.GONE
|
||||
binding.ivRecord.setImageResource(R.mipmap.copy)
|
||||
}
|
||||
}
|
||||
|
||||
binding.llVoice.setOnClickListener {
|
||||
isVoiceEnabled = !isVoiceEnabled
|
||||
if (isVoiceEnabled) {
|
||||
Glide.with(this)
|
||||
.asGif()
|
||||
.load(R.mipmap.voice_open)
|
||||
.into(binding.ivVoice)
|
||||
} else {
|
||||
binding.ivVoice.setImageResource(R.mipmap.voice)
|
||||
}
|
||||
}
|
||||
|
||||
binding.ivUp.setOnTouchListener { v, event ->
|
||||
handlePtzTouch(
|
||||
view = v,
|
||||
event = event,
|
||||
direction = "up",
|
||||
action = { deviceNo }
|
||||
)
|
||||
}
|
||||
|
||||
binding.ivDown.setOnTouchListener { v, event ->
|
||||
handlePtzTouch(
|
||||
view = v,
|
||||
event = event,
|
||||
direction = "down",
|
||||
action = { deviceNo }
|
||||
)
|
||||
}
|
||||
|
||||
binding.ivLeft.setOnTouchListener { v, event ->
|
||||
handlePtzTouch(
|
||||
view = v,
|
||||
event = event,
|
||||
direction = "left",
|
||||
action = { deviceNo }
|
||||
)
|
||||
}
|
||||
|
||||
binding.ivRight.setOnTouchListener { v, event ->
|
||||
handlePtzTouch(
|
||||
view = v,
|
||||
event = event,
|
||||
direction = "right",
|
||||
action = { deviceNo }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handlePtzTouch(
|
||||
view: View,
|
||||
event: MotionEvent,
|
||||
direction: String,
|
||||
action: () -> String?
|
||||
): Boolean {
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
view.isPressed = true
|
||||
val deviceNo = action()
|
||||
if (!deviceNo.isNullOrEmpty()) {
|
||||
startPtz(deviceNo = deviceNo, direction = direction)
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
view.isPressed = false
|
||||
stopCurrentPtz()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun startPtz(deviceNo: String, direction: String) {
|
||||
stopCurrentPtz()
|
||||
|
||||
currentPtzDirection = direction
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val response = when (direction) {
|
||||
"up" -> RetrofitNetwork.getNetworkService().ptzUp(deviceNo)
|
||||
"down" -> RetrofitNetwork.getNetworkService().ptzDown(deviceNo)
|
||||
"left" -> RetrofitNetwork.getNetworkService().ptzLeft(deviceNo)
|
||||
"right" -> RetrofitNetwork.getNetworkService().ptzRight(deviceNo)
|
||||
else -> null
|
||||
}
|
||||
Log.d("LV", "PTZ $direction start response: ${response?.code}")
|
||||
} catch (e: Exception) {
|
||||
Log.e("LV", "PTZ $direction start failed", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun shoot(deviceNo: String) {
|
||||
Log.d("LV", "btnCapture click, deviceNo=$deviceNo, duration=0")
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().ptzShoot(
|
||||
deviceNo = deviceNo,
|
||||
duration = "0"
|
||||
)
|
||||
Log.d("LV", "PTZ shoot response: code=${response.code}, msg=${response.msg}")
|
||||
} catch (e: Exception) {
|
||||
Log.e("LV", "PTZ shoot failed", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopCurrentPtz() {
|
||||
val direction = currentPtzDirection ?: return
|
||||
currentPtzDirection = null
|
||||
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().ptzStop(deviceNo ?: return@launch)
|
||||
Log.d("LV", "PTZ $direction stop response: ${response.code}")
|
||||
} catch (e: Exception) {
|
||||
Log.e("LV", "PTZ $direction stop failed", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchAlarmList(page: Int = 1) {
|
||||
val currentDeviceId = deviceId ?: return
|
||||
isLoading = true
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().getDeviceAlarmList(
|
||||
deviceId = currentDeviceId,
|
||||
pageNum = page.toString(),
|
||||
pageSize = pageSize.toString()
|
||||
)
|
||||
Log.d("LiveVideoActivity", "总条数: ${response.total}, 当前页数据条数: ${response.rows.size}")
|
||||
val newData = response.rows
|
||||
|
||||
totalPage = if (response.total % pageSize == 0) {
|
||||
response.total / pageSize
|
||||
} else {
|
||||
response.total / pageSize + 1
|
||||
}
|
||||
|
||||
if (page == 1) {
|
||||
alarmList.clear()
|
||||
hasMore = totalPage > 1
|
||||
}
|
||||
alarmList.addAll(newData)
|
||||
alarmAdapter?.notifyDataSetChanged()
|
||||
updateAlarmListState()
|
||||
} catch (e: Exception) {
|
||||
Log.e("LiveVideoActivity", "请求告警列表失败", e)
|
||||
hasMore = false
|
||||
showAlarmListNetworkError()
|
||||
} finally {
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateAlarmListState() {
|
||||
if (alarmList.isEmpty()) {
|
||||
binding.alarmLogRecyclerView.visibility = View.GONE
|
||||
binding.layoutNoPermission.visibility = View.VISIBLE
|
||||
binding.layoutNoNetwork.visibility = View.GONE
|
||||
} else {
|
||||
binding.alarmLogRecyclerView.visibility = View.VISIBLE
|
||||
binding.layoutNoPermission.visibility = View.GONE
|
||||
binding.layoutNoNetwork.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun showAlarmListNetworkError() {
|
||||
binding.alarmLogRecyclerView.visibility = View.GONE
|
||||
binding.layoutNoPermission.visibility = View.GONE
|
||||
binding.layoutNoNetwork.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.exoPlayContextId.onVideoResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
binding.exoPlayContextId.onVideoPause()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
ptzHandler.removeCallbacksAndMessages(null)
|
||||
orientationUtils?.releaseListener()
|
||||
binding.exoPlayContextId.release()
|
||||
stopStream()
|
||||
}
|
||||
|
||||
private fun stopStream() {
|
||||
val no = deviceNo ?: return
|
||||
GlobalScope.launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().videoStop(no)
|
||||
Log.d("直播流停止", "videoStop response: code=${response.code}, msg=${response.msg}")
|
||||
} catch (e: Exception) {
|
||||
Log.e("直播流停止", "停止推流异常", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.base.BaseActivity
|
||||
import com.example.defenseapplication.databinding.SettingsActivityBinding
|
||||
import com.example.defenseapplication.utils.DeviceIdEvent
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.view.CustomDialogFragmentText
|
||||
import com.example.defenseapplication.view.RecognitionModeDialog
|
||||
import com.example.defenseapplication.bean.VerifyOptionPasswordRequest
|
||||
import com.example.defenseapplication.personal.PasswordInputDialog
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.base.BaseActivity
|
||||
import com.ckkj.defense_device.databinding.SettingsActivityBinding
|
||||
import com.ckkj.defense_device.utils.DeviceIdEvent
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.CustomDialogFragmentText
|
||||
import com.ckkj.defense_device.view.RecognitionModeDialog
|
||||
import com.ckkj.defense_device.bean.VerifyOptionPasswordRequest
|
||||
import com.ckkj.defense_device.personal.PasswordInputDialog
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -27,6 +27,7 @@ class SettingsActivity : BaseActivity() {
|
||||
private var alertAudio: String? = null
|
||||
private var audioContent: String? = null
|
||||
private var isPasswordVerified = false
|
||||
private var verifiedPassword: String? = null
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
@@ -55,15 +56,15 @@ class SettingsActivity : BaseActivity() {
|
||||
if (isPasswordVerified) {
|
||||
val dialog = RecognitionModeDialog(this)
|
||||
dialog.setOnConfirmListener { mode ->
|
||||
updateRecognitionMode(mode)
|
||||
updateRecognitionMode(mode, verifiedPassword)
|
||||
}
|
||||
dialog.show()
|
||||
} else {
|
||||
showPasswordDialog {
|
||||
showPasswordDialog { inputPassword ->
|
||||
isPasswordVerified = true
|
||||
val dialog = RecognitionModeDialog(this)
|
||||
dialog.setOnConfirmListener { mode ->
|
||||
updateRecognitionMode(mode)
|
||||
updateRecognitionMode(mode, inputPassword)
|
||||
}
|
||||
dialog.show()
|
||||
}
|
||||
@@ -94,22 +95,24 @@ class SettingsActivity : BaseActivity() {
|
||||
}
|
||||
binding.itemWaterGunSetting.setOnClickListener {
|
||||
if (isPasswordVerified) {
|
||||
navigateToWaterGunSettings()
|
||||
navigateToWaterGunSettings(verifiedPassword)
|
||||
} else {
|
||||
showPasswordDialog {
|
||||
showPasswordDialog { inputPassword ->
|
||||
isPasswordVerified = true
|
||||
navigateToWaterGunSettings()
|
||||
navigateToWaterGunSettings(inputPassword)
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.itemAutoMode.setOnClickListener {
|
||||
if (isPasswordVerified) {
|
||||
val intent = Intent(this, AutoModeActivity::class.java)
|
||||
intent.putExtra("optionPassword", verifiedPassword)
|
||||
startActivity(intent)
|
||||
} else {
|
||||
showPasswordDialog {
|
||||
showPasswordDialog { inputPassword ->
|
||||
isPasswordVerified = true
|
||||
val intent = Intent(this, AutoModeActivity::class.java)
|
||||
intent.putExtra("optionPassword", inputPassword)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
@@ -183,7 +186,7 @@ class SettingsActivity : BaseActivity() {
|
||||
binding.tvRelatedUsers.text = "$count 人"
|
||||
}
|
||||
|
||||
private fun updateDeviceInfo(device: com.example.defenseapplication.bean.DeviceBean) {
|
||||
private fun updateDeviceInfo(device: com.ckkj.defense_device.bean.DeviceBean) {
|
||||
binding.tvDeviceName.text = device.deviceName ?: "未设置"
|
||||
binding.tvWifiName.text = device.wifiName ?: "未设置"
|
||||
|
||||
@@ -236,7 +239,7 @@ class SettingsActivity : BaseActivity() {
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val deviceBean = com.example.defenseapplication.bean.DeviceBean(
|
||||
val deviceBean = com.ckkj.defense_device.bean.DeviceBean(
|
||||
id = deviceId,
|
||||
deviceName = name,
|
||||
)
|
||||
@@ -258,7 +261,7 @@ class SettingsActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateRecognitionMode(mode: String) {
|
||||
private fun updateRecognitionMode(mode: String, optionPassword: String?) {
|
||||
val deviceId = DeviceIdEvent.getDeviceId()
|
||||
if (deviceId.isNullOrEmpty()) {
|
||||
Toast.makeText(this, "设备ID为空", Toast.LENGTH_SHORT).show()
|
||||
@@ -273,9 +276,10 @@ class SettingsActivity : BaseActivity() {
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val deviceBean = com.example.defenseapplication.bean.DeviceBean(
|
||||
val deviceBean = com.ckkj.defense_device.bean.DeviceBean(
|
||||
id = deviceId,
|
||||
patternPerception = patternPerception,
|
||||
optionPassword = optionPassword
|
||||
)
|
||||
val response = RetrofitNetwork.getNetworkService().updateDeviceInfo(deviceBean)
|
||||
withContext(Dispatchers.Main) {
|
||||
@@ -305,13 +309,13 @@ class SettingsActivity : BaseActivity() {
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val deleteBean = com.example.defenseapplication.bean.DeleteBean()
|
||||
val deleteBean = com.ckkj.defense_device.bean.DeleteBean()
|
||||
deleteBean.deviceId = deviceId
|
||||
val response = RetrofitNetwork.getNetworkService().deleteDevice(deleteBean)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200) {
|
||||
Toast.makeText(this@SettingsActivity, "解绑成功", Toast.LENGTH_SHORT).show()
|
||||
val intent = Intent(this@SettingsActivity, com.example.defenseapplication.home.HomeActivity::class.java)
|
||||
val intent = Intent(this@SettingsActivity, com.ckkj.defense_device.home.HomeActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
startActivity(intent)
|
||||
finish()
|
||||
@@ -328,7 +332,7 @@ class SettingsActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPasswordDialog(onVerified: () -> Unit) {
|
||||
private fun showPasswordDialog(onVerified: (String) -> Unit) {
|
||||
passwordDialog = PasswordInputDialog(this).apply {
|
||||
setOnConfirmListener { inputPassword ->
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
@@ -338,7 +342,8 @@ class SettingsActivity : BaseActivity() {
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200) {
|
||||
dismiss()
|
||||
onVerified()
|
||||
verifiedPassword = inputPassword
|
||||
onVerified(inputPassword)
|
||||
} else {
|
||||
Toast.makeText(
|
||||
this@SettingsActivity,
|
||||
@@ -365,8 +370,9 @@ class SettingsActivity : BaseActivity() {
|
||||
passwordDialog.show()
|
||||
}
|
||||
|
||||
private fun navigateToWaterGunSettings() {
|
||||
private fun navigateToWaterGunSettings(optionPassword: String? = null) {
|
||||
val intent = Intent(this, WaterGunSettingsActivity::class.java)
|
||||
intent.putExtra("optionPassword", optionPassword)
|
||||
val deviceId = DeviceIdEvent.getDeviceId()
|
||||
if (!deviceId.isNullOrEmpty()) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
@@ -1,17 +1,17 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.os.Bundle
|
||||
import android.widget.ImageView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.bean.DeviceBean
|
||||
import com.example.defenseapplication.databinding.StrikePositionActivityBinding
|
||||
import com.example.defenseapplication.utils.DeviceIdEvent
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.view.CustomDialogFragment
|
||||
import com.example.defenseapplication.view.showDefenseDialog
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.bean.DeviceBean
|
||||
import com.ckkj.defense_device.databinding.StrikePositionActivityBinding
|
||||
import com.ckkj.defense_device.utils.DeviceIdEvent
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.CustomDialogFragment
|
||||
import com.ckkj.defense_device.view.showDefenseDialog
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -45,7 +45,7 @@ class StrikePositionActivity : AppCompatActivity() {
|
||||
|
||||
private var selectedZone: Zone = Zone.CHEST
|
||||
|
||||
// Touch tracking for ImageView (captured in onTouch, used in ACTION_UP for click detection)
|
||||
// ImageView 的触控追踪(在 onTouch 中捕获,ACTION_UP 用于点击检测)
|
||||
private var lastTouchX = 0f
|
||||
private var lastTouchY = 0f
|
||||
|
||||
@@ -67,7 +67,7 @@ class StrikePositionActivity : AppCompatActivity() {
|
||||
binding.ivBack.setOnClickListener { finish() }
|
||||
binding.btnSubmit.setOnClickListener { showConfirmDialog() }
|
||||
|
||||
// Use OnTouchListener to track touch coordinates
|
||||
// 使用 OnTouchListen 来跟踪触摸坐标
|
||||
binding.ivHumanBody.setOnTouchListener { _, event ->
|
||||
lastTouchX = event.x
|
||||
lastTouchY = event.y
|
||||
@@ -77,7 +77,7 @@ class StrikePositionActivity : AppCompatActivity() {
|
||||
false
|
||||
}
|
||||
|
||||
// OnClick fires on ACTION_UP; coordinates captured from lastTouchX/Y
|
||||
// OnClick 对ACTION_UP开火;坐标来自lastTouchXY
|
||||
binding.ivHumanBody.setOnClickListener {
|
||||
val imageView = it as ImageView
|
||||
val (nx, ny) = resolveTapLocation(lastTouchX, lastTouchY, imageView)
|
||||
@@ -100,10 +100,12 @@ class StrikePositionActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a screen coordinate (from onTouch) into a normalised [0..1] offset
|
||||
* inside the drawable, accounting for:
|
||||
* - ImageView scaling (scaleType="fitCenter" adds letterboxing)
|
||||
* - Letterbox / pillarbox margins when image aspect ≠ view aspect
|
||||
* 这段代码将触摸坐标转换为图片内部的归一化位置:
|
||||
*
|
||||
* 1. 计算图片等比缩放后的实际尺寸
|
||||
* 2. 计算letterbox/pillarbox的偏移量
|
||||
* 3. 将触摸点限制在图片有效区域内
|
||||
* 4. 返回相对于图片的归一化坐标(0-1范围)
|
||||
*/
|
||||
private fun resolveTapLocation(rawX: Float, rawY: Float, imageView: ImageView): Pair<Float, Float> {
|
||||
val drawable = imageView.drawable ?: return Pair(0f, 0f)
|
||||
@@ -114,22 +116,22 @@ class StrikePositionActivity : AppCompatActivity() {
|
||||
val intrinsicWidth = drawable.intrinsicWidth.toFloat()
|
||||
val intrinsicHeight = drawable.intrinsicHeight.toFloat()
|
||||
|
||||
// scale: the uniform factor the image is scaled by to fit the view
|
||||
// 比例:图像被缩放以适应视图的均匀因子
|
||||
val scale = min(ivWidth / intrinsicWidth, ivHeight / intrinsicHeight)
|
||||
|
||||
// Physical pixel size of the drawable after scaling
|
||||
// 缩放后绘制的物理像素大小
|
||||
val drawnW = intrinsicWidth * scale
|
||||
val drawnH = intrinsicHeight * scale
|
||||
|
||||
// Letterbox offsets (top / left) when aspect ratios differ
|
||||
// 当宽高比不同时,信箱偏移(左上角)
|
||||
val drawableLeft = (ivWidth - drawnW) / 2f
|
||||
val drawableTop = (ivHeight - drawnH) / 2f
|
||||
|
||||
// Clamp touch to the actual drawable area
|
||||
// 夹紧触地接触实际可绘制区域
|
||||
val clampedX = max(drawableLeft, min(rawX, drawableLeft + drawnW))
|
||||
val clampedY = max(drawableTop, min(rawY, drawableTop + drawnH))
|
||||
|
||||
// Normalised offset [0..1] within the drawable
|
||||
// 可绘制物内的归一化偏移 [0..1]
|
||||
val normalizedX = (clampedX - drawableLeft) / drawnW
|
||||
val normalizedY = (clampedY - drawableTop) / drawnH
|
||||
|
||||
@@ -137,14 +139,11 @@ class StrikePositionActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Zones are divided by:
|
||||
* - Horizontal boundary at ny = 0.5 → top = HEAD, bottom = shoulders
|
||||
* - Vertical boundary 1 at nx = 1/3 → left = LEFT_SHOULDER
|
||||
* - Vertical boundary 2 at nx = 2/3 → right = RIGHT_SHOULDER, middle = CHEST
|
||||
* 这段代码根据归一化坐标确定触摸区域:
|
||||
*
|
||||
* If the touch falls within ±tolerance of any boundary line, the nearest
|
||||
* zone centre (Euclidean distance in normalised space) is used to avoid
|
||||
* arbitrary assignments at boundary pixels.
|
||||
* 1. 将图片分为头部、左肩、胸部、右肩四个区域
|
||||
* 2. 边界附近±0.04范围内,使用最近区域中心避免误判
|
||||
* 3. 上半部分为头部,下半部分按1/3和2/3垂直线划分
|
||||
*/
|
||||
private fun zoneForLocation(nx: Float, ny: Float): Zone {
|
||||
val hBoundary = 0.5f
|
||||
@@ -168,7 +167,14 @@ class StrikePositionActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the Zone whose normalised centre is closest (Euclidean) to (nx, ny). */
|
||||
/**
|
||||
* 这段代码找到距离触摸点最近的区域:
|
||||
*
|
||||
* 1. 遍历所有Zone,计算与触摸点的欧氏距离平方
|
||||
* 2. 返回距离最小的Zone作为结果
|
||||
* 3. 若无匹配则默认返回CHEST
|
||||
* */
|
||||
|
||||
private fun nearestZone(nx: Float, ny: Float): Zone {
|
||||
return Zone.values().minByOrNull { zone ->
|
||||
val dx = nx - zone.normalizedX
|
||||
@@ -178,12 +184,12 @@ class StrikePositionActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Positions the marker (ivStrikeMarker) at the zone's centre, clamped so the
|
||||
* marker never goes out of the ivHumanBody bounds.
|
||||
*
|
||||
* Because the marker is a child of ivHumanBody and starts at its center
|
||||
* (layout_gravity="center"), we compute the offset from that center point
|
||||
* and apply it via translationX/Y so the marker's layout bounds stay intact.
|
||||
这段代码更新标记位置到区域中心:
|
||||
|
||||
1. 根据Zone的归一化坐标计算目标位置
|
||||
2. 限制标记不超出图片边界(Y仅限制上限)
|
||||
3. 相对于ImageView中心计算偏移量并应用
|
||||
4. 支持动画或即时移动两种方式
|
||||
*/
|
||||
private fun updateMarkerPosition(zone: Zone, animated: Boolean) {
|
||||
if (humanBodyWidth <= 0 || humanBodyHeight <= 0) return
|
||||
@@ -198,9 +204,7 @@ class StrikePositionActivity : AppCompatActivity() {
|
||||
val rawX = humanBodyWidth * zone.normalizedX
|
||||
val rawY = humanBodyHeight * zone.normalizedY
|
||||
|
||||
// Clamp X so the marker never extends beyond the drawable edges.
|
||||
// Y clamp only has an upper bound — HEAD at normalizedY=0 is allowed to go
|
||||
// all the way to the top (translationY can be negative).
|
||||
//用X夹住,使标记永远不会超出可绘制的边缘。Y钳只有一个上界——在归一化Y=0处的HEAD可以一直达到顶端(平移Y可以为负)。
|
||||
val clampedX = min(max(rawX, halfMarkerW), humanBodyWidth - halfMarkerW)
|
||||
val clampedY = min(rawY, humanBodyHeight - halfMarkerH)
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.bean.DeleteDeviceUserRequest
|
||||
import com.example.defenseapplication.bean.ObtainInviterInformationRequest
|
||||
import com.example.defenseapplication.bean.VerifyOptionPasswordRequest
|
||||
import com.example.defenseapplication.personal.PasswordInputDialog
|
||||
import com.example.defenseapplication.utils.DeviceIdEvent
|
||||
import com.example.defenseapplication.utils.DeviceUserUpdateEvent
|
||||
import com.example.defenseapplication.databinding.UserDetailsActivityBinding
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.view.CustomDialogFragmentText
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.bean.DeleteDeviceUserRequest
|
||||
import com.ckkj.defense_device.bean.ObtainInviterInformationRequest
|
||||
import com.ckkj.defense_device.bean.UpdateFamilyUserRequest
|
||||
import com.ckkj.defense_device.bean.VerifyOptionPasswordRequest
|
||||
import com.ckkj.defense_device.personal.PasswordInputDialog
|
||||
import com.ckkj.defense_device.utils.DeviceIdEvent
|
||||
import com.ckkj.defense_device.utils.DeviceUserUpdateEvent
|
||||
import com.ckkj.defense_device.databinding.UserDetailsActivityBinding
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.CustomDialogFragmentText
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -27,6 +27,7 @@ class UserDetailsActivity : AppCompatActivity() {
|
||||
private var userId: String = ""
|
||||
private var isPasswordVerified: Boolean = false
|
||||
private lateinit var passwordDialog: PasswordInputDialog
|
||||
private var optionPassword: String = ""
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -73,8 +74,8 @@ class UserDetailsActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateUI(data: com.example.defenseapplication.bean.ObtainInviterInformationBean) {
|
||||
binding.tvContactName.text = data.nickName ?: "未知用户"
|
||||
private fun updateUI(data: com.ckkj.defense_device.bean.ObtainInviterInformationBean) {
|
||||
binding.tvContactName.text = data.nickName ?: ""
|
||||
binding.tvPhone.text = data.phonenumber ?: ""
|
||||
binding.tvIdCard.text = data.idCard ?: ""
|
||||
binding.tvMacAddress.text = data.mac ?: ""
|
||||
@@ -88,10 +89,12 @@ class UserDetailsActivity : AppCompatActivity() {
|
||||
binding.swUserStatus.setOnCheckedChangeListener { _, isChecked ->
|
||||
if (!isPasswordVerified) {
|
||||
binding.swUserStatus.isChecked = !isChecked
|
||||
showPasswordDialog {
|
||||
showPasswordDialog(isChecked) {
|
||||
isPasswordVerified = true
|
||||
binding.swUserStatus.isChecked = isChecked
|
||||
}
|
||||
} else {
|
||||
updateFamilyUserStatus(isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +103,7 @@ class UserDetailsActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPasswordDialog(onVerified: () -> Unit) {
|
||||
private fun showPasswordDialog(status: Boolean, onVerified: () -> Unit) {
|
||||
passwordDialog = PasswordInputDialog(this).apply {
|
||||
setOnConfirmListener { inputPassword ->
|
||||
lifecycleScope.launch {
|
||||
@@ -110,6 +113,7 @@ class UserDetailsActivity : AppCompatActivity() {
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200) {
|
||||
dismiss()
|
||||
updateFamilyUserStatus(status, inputPassword)
|
||||
onVerified()
|
||||
} else {
|
||||
Toast.makeText(
|
||||
@@ -136,6 +140,48 @@ class UserDetailsActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
|
||||
private fun updateFamilyUserStatus(status: Boolean) {
|
||||
updateFamilyUserStatus(status, optionPassword)
|
||||
}
|
||||
|
||||
private fun updateFamilyUserStatus(status: Boolean, password: String) {
|
||||
if (userId.isEmpty()) {
|
||||
Toast.makeText(this, "用户ID为空", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
if (password.isNotEmpty()) {
|
||||
optionPassword = password
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val request = UpdateFamilyUserRequest(
|
||||
id = userId,
|
||||
optionPassword = optionPassword,
|
||||
optionStatus = "status",
|
||||
status = if (status) "1" else "0"
|
||||
)
|
||||
val response = RetrofitNetwork.getNetworkService().updateFamilyUser(request)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200) {
|
||||
Toast.makeText(this@UserDetailsActivity, "状态修改成功", Toast.LENGTH_SHORT).show()
|
||||
DeviceUserUpdateEvent.notifyUpdate()
|
||||
} else {
|
||||
Toast.makeText(this@UserDetailsActivity, response.msg ?: "状态修改失败", Toast.LENGTH_SHORT).show()
|
||||
binding.swUserStatus.isChecked = !status
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast.makeText(this@UserDetailsActivity, "网络请求失败", Toast.LENGTH_SHORT).show()
|
||||
binding.swUserStatus.isChecked = !status
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showDeleteDialog() {
|
||||
val dialog = CustomDialogFragmentText()
|
||||
dialog.setTitle(getString(R.string.tip))
|
||||
@@ -147,7 +193,7 @@ class UserDetailsActivity : AppCompatActivity() {
|
||||
if (isPasswordVerified) {
|
||||
deleteDeviceUser()
|
||||
} else {
|
||||
showPasswordDialog {
|
||||
showPasswordDialog(false) {
|
||||
isPasswordVerified = true
|
||||
deleteDeviceUser()
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.bean.DeviceBean
|
||||
import com.example.defenseapplication.databinding.VoiceSettingsActivityBinding
|
||||
import com.example.defenseapplication.utils.ApiService
|
||||
import com.example.defenseapplication.utils.DeviceIdEvent
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.bean.DeviceBean
|
||||
import com.ckkj.defense_device.databinding.VoiceSettingsActivityBinding
|
||||
import com.ckkj.defense_device.utils.ApiService
|
||||
import com.ckkj.defense_device.utils.DeviceIdEvent
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -79,8 +79,7 @@ class VoiceSettingsActivity : AppCompatActivity() {
|
||||
private fun updateDeviceAlertAudio() {
|
||||
deviceId?.let { id ->
|
||||
val newAlertAudio = if (binding.swWarningVoice.isChecked) "1" else "0"
|
||||
// 只有状态发生变化时才请求
|
||||
if (newAlertAudio != originalAlertAudio) {
|
||||
// 点击返回时总是触发网络请求
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val deviceBean = DeviceBean(id = id, alertAudio = newAlertAudio)
|
||||
@@ -89,20 +88,23 @@ class VoiceSettingsActivity : AppCompatActivity() {
|
||||
if (response.code == 200 && response.data != null) {
|
||||
Toast.makeText(this@VoiceSettingsActivity, "修改成功", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
// 仅在状态实际发生变化时才显示错误提示
|
||||
if (newAlertAudio != originalAlertAudio) {
|
||||
Toast.makeText(this@VoiceSettingsActivity, response.msg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
finish()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
// 仅在状态实际发生变化时才显示失败提示
|
||||
if (newAlertAudio != originalAlertAudio) {
|
||||
Toast.makeText(this@VoiceSettingsActivity, "修改失败", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
@@ -6,10 +6,10 @@ import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.widget.doAfterTextChanged
|
||||
import com.example.defenseapplication.bean.DeviceBean
|
||||
import com.example.defenseapplication.databinding.WarningVoiceContentActivityBinding
|
||||
import com.example.defenseapplication.utils.ApiService
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.bean.DeviceBean
|
||||
import com.ckkj.defense_device.databinding.WarningVoiceContentActivityBinding
|
||||
import com.ckkj.defense_device.utils.ApiService
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -1,16 +1,15 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.base.BaseActivity
|
||||
import com.example.defenseapplication.bean.DeviceBean
|
||||
import com.example.defenseapplication.databinding.WaterGunSettingsActivityBinding
|
||||
import com.example.defenseapplication.utils.DeviceIdEvent
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.view.ContainerSelectDialog
|
||||
import com.example.defenseapplication.view.CustomDialogFragmentText
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.base.BaseActivity
|
||||
import com.ckkj.defense_device.bean.DeviceBean
|
||||
import com.ckkj.defense_device.databinding.WaterGunSettingsActivityBinding
|
||||
import com.ckkj.defense_device.utils.DeviceIdEvent
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.ContainerSelectDialog
|
||||
import com.ckkj.defense_device.view.CustomDialogFragmentText
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -25,6 +24,7 @@ class WaterGunSettingsActivity : BaseActivity() {
|
||||
private var currentStrikeRange: String = "7"
|
||||
private var currentStrikeInterval: String = "3"
|
||||
private var currentContainer: String = "容器4"
|
||||
private var optionPassword: String? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -42,6 +42,7 @@ class WaterGunSettingsActivity : BaseActivity() {
|
||||
currentStrikeRange = intent.getStringExtra("strikeRange") ?: "7"
|
||||
currentStrikeInterval = intent.getStringExtra("strikeInterval") ?: "3"
|
||||
currentContainer = intent.getStringExtra("container") ?: "容器4"
|
||||
optionPassword = intent.getStringExtra("optionPassword")
|
||||
|
||||
// 显示初始值
|
||||
binding.tvDistance.text = "${currentStrikeRange}m"
|
||||
@@ -101,7 +102,8 @@ class WaterGunSettingsActivity : BaseActivity() {
|
||||
try {
|
||||
val deviceBean = DeviceBean(
|
||||
id = deviceId,
|
||||
strikeRange = distance
|
||||
strikeRange = distance,
|
||||
optionPassword = optionPassword
|
||||
)
|
||||
val response = RetrofitNetwork.getNetworkService().updateDeviceInfo(deviceBean)
|
||||
withContext(Dispatchers.Main) {
|
||||
@@ -132,7 +134,8 @@ class WaterGunSettingsActivity : BaseActivity() {
|
||||
try {
|
||||
val deviceBean = DeviceBean(
|
||||
id = deviceId,
|
||||
strikeInterval = interval
|
||||
strikeInterval = interval,
|
||||
optionPassword = optionPassword
|
||||
)
|
||||
val response = RetrofitNetwork.getNetworkService().updateDeviceInfo(deviceBean)
|
||||
withContext(Dispatchers.Main) {
|
||||
@@ -163,7 +166,8 @@ class WaterGunSettingsActivity : BaseActivity() {
|
||||
try {
|
||||
val deviceBean = DeviceBean(
|
||||
id = deviceId,
|
||||
container = container
|
||||
container = container,
|
||||
optionPassword = optionPassword
|
||||
)
|
||||
val response = RetrofitNetwork.getNetworkService().updateDeviceInfo(deviceBean)
|
||||
withContext(Dispatchers.Main) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.liveVideo
|
||||
package com.ckkj.defense_device.liveVideo
|
||||
|
||||
import android.Manifest
|
||||
import android.content.BroadcastReceiver
|
||||
@@ -18,13 +18,13 @@ import android.widget.PopupWindow
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.adapter.WifiListAdapter
|
||||
import com.example.defenseapplication.bean.DeviceBean
|
||||
import com.example.defenseapplication.databinding.DialogWifiListBinding
|
||||
import com.example.defenseapplication.databinding.WifiManagementActivityBinding
|
||||
import com.example.defenseapplication.utils.DeviceIdEvent
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.adapter.WifiListAdapter
|
||||
import com.ckkj.defense_device.bean.DeviceBean
|
||||
import com.ckkj.defense_device.databinding.DialogWifiListBinding
|
||||
import com.ckkj.defense_device.databinding.WifiManagementActivityBinding
|
||||
import com.ckkj.defense_device.utils.DeviceIdEvent
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -202,14 +202,6 @@ class WiFiManagementActivity : AppCompatActivity() {
|
||||
}
|
||||
dialogBinding.rvWifiList.adapter = adapter
|
||||
|
||||
// 添加下拉刷新功能
|
||||
dialogBinding.swipeRefreshLayout.setOnRefreshListener {
|
||||
wifiManager.startScan()
|
||||
// 延迟1秒后停止刷新动画
|
||||
android.os.Handler().postDelayed({
|
||||
dialogBinding.swipeRefreshLayout.isRefreshing = false
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateBottomButtonVisibility() {
|
||||
@@ -229,9 +221,6 @@ class WiFiManagementActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun updateWifiList() {
|
||||
popupWindow?.contentView?.findViewById<androidx.swiperefreshlayout.widget.SwipeRefreshLayout>(R.id.swipeRefreshLayout)?.let { swipeRefreshLayout ->
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
}
|
||||
popupWindow?.contentView?.findViewById<androidx.recyclerview.widget.RecyclerView>(R.id.rvWifiList)?.let { recyclerView ->
|
||||
val wifiList = getWifiList()
|
||||
recyclerView.adapter = WifiListAdapter(wifiList) { wifiName ->
|
||||
@@ -1,14 +1,9 @@
|
||||
package com.example.defenseapplication.login
|
||||
package com.ckkj.defense_device.login
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.FaceLoginActivityBinding
|
||||
import com.ckkj.defense_device.databinding.FaceLoginActivityBinding
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
//人脸识别
|
||||
class FaceLoginActivity : AppCompatActivity() {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.login
|
||||
package com.ckkj.defense_device.login
|
||||
|
||||
import android.Manifest
|
||||
import android.content.pm.PackageManager
|
||||
@@ -13,8 +13,9 @@ import androidx.camera.core.Preview
|
||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.example.defenseapplication.databinding.FaceVerificationActivityBinding
|
||||
import com.example.defenseapplication.view.FaceAnalyzer
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.databinding.FaceVerificationActivityBinding
|
||||
import com.ckkj.defense_device.view.FaceAnalyzer
|
||||
import com.google.mlkit.vision.face.FaceDetection
|
||||
import com.google.mlkit.vision.face.FaceDetectorOptions
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
@@ -106,7 +107,7 @@ class FaceVerificationActivity : AppCompatActivity() {
|
||||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
startCamera()
|
||||
} else {
|
||||
Toast.makeText(this, "需要相机权限才能进行人脸验证", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, R.string.need_camera_permission_for_face_verify, Toast.LENGTH_SHORT).show()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.login
|
||||
package com.ckkj.defense_device.login
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
@@ -7,9 +7,10 @@ import android.os.CountDownTimer
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import bean.ForgotRequest
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.ForgetPasswordActivityBinding
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.databinding.ForgetPasswordActivityBinding
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.LoadingDialog
|
||||
import com.google.firebase.crashlytics.buildtools.reloc.org.apache.http.util.TextUtils
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -20,6 +21,7 @@ import java.util.regex.Pattern
|
||||
|
||||
class ForgetPasswordActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ForgetPasswordActivityBinding
|
||||
private var isLoading = false
|
||||
private var countDownTimer: CountDownTimer? = null
|
||||
private var isSendingCode = false
|
||||
|
||||
@@ -55,17 +57,19 @@ class ForgetPasswordActivity : AppCompatActivity() {
|
||||
if (isPhoneNumberValid(phoneNumber)) {
|
||||
sendVerificationCode(phoneNumber)
|
||||
} else {
|
||||
Toast.makeText(this, "请输入有效的11位手机号", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, getString(R.string.phone_tip), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this, "请稍后再试", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, getString(R.string.please_try_later), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
binding.btnNext.setOnClickListener {
|
||||
if (!isLoading) {
|
||||
performResetPassword()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isPhoneNumberValid(phone: String): Boolean {
|
||||
if (TextUtils.isEmpty(phone)) return false
|
||||
@@ -82,7 +86,7 @@ class ForgetPasswordActivity : AppCompatActivity() {
|
||||
val response = RetrofitNetwork.getNetworkService().getCode(phoneNumber)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200) {
|
||||
Toast.makeText(this@ForgetPasswordActivity, "验证码已发送", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this@ForgetPasswordActivity, getString(R.string.code_sent_to), Toast.LENGTH_SHORT).show()
|
||||
startCountDown()
|
||||
} else {
|
||||
Toast.makeText(this@ForgetPasswordActivity, response.msg, Toast.LENGTH_SHORT).show()
|
||||
@@ -104,11 +108,10 @@ class ForgetPasswordActivity : AppCompatActivity() {
|
||||
* 开始验证码按钮倒计时
|
||||
*/
|
||||
private fun startCountDown() {
|
||||
binding.sendCodeBtn.isEnabled = false
|
||||
countDownTimer = object : CountDownTimer(COUNTDOWN_DURATION, COUNTDOWN_INTERVAL) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
val secondsRemaining = (millisUntilFinished / 1000).toInt()
|
||||
binding.sendCodeBtn.text = "${secondsRemaining}秒后重试"
|
||||
binding.sendCodeBtn.isEnabled = false
|
||||
binding.sendCodeBtn.text = getString(R.string.countdown_retry, millisUntilFinished / 1000)
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
@@ -123,7 +126,7 @@ class ForgetPasswordActivity : AppCompatActivity() {
|
||||
private fun resetSendButton() {
|
||||
countDownTimer?.cancel()
|
||||
countDownTimer = null
|
||||
binding.sendCodeBtn.text = "发送验证码"
|
||||
binding.sendCodeBtn.text = getString(R.string.resend_code)
|
||||
binding.sendCodeBtn.isEnabled = true
|
||||
}
|
||||
|
||||
@@ -137,34 +140,38 @@ class ForgetPasswordActivity : AppCompatActivity() {
|
||||
val confirmPassword = binding.etInviteCode.text.toString().trim()
|
||||
|
||||
if (!isPhoneNumberValid(phoneNumber)) {
|
||||
Toast.makeText(this, "手机号格式不正确", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, getString(R.string.invalid_phone), Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(smsCode)) {
|
||||
Toast.makeText(this, "请输入验证码", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, getString(R.string.hint_code_zh), Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(newPassword) || TextUtils.isEmpty(confirmPassword)) {
|
||||
Toast.makeText(this, "密码不能为空", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, getString(R.string.password_cannot_empty), Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
if (newPassword.length < MIN_PASSWORD_LENGTH || newPassword.length > MAX_PASSWORD_LENGTH) {
|
||||
Toast.makeText(this, "密码长度需为${MIN_PASSWORD_LENGTH}-${MAX_PASSWORD_LENGTH}位", Toast.LENGTH_SHORT).show()
|
||||
val tip = getString(R.string.pwd_length_tip, MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH)
|
||||
Toast.makeText(this, tip, Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
if (!newPassword.matches(Regex(".*[A-Za-z].*")) || !newPassword.matches(Regex(".*[0-9].*"))) {
|
||||
Toast.makeText(this, "密码需同时包含字母和数字", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, getString(R.string.password_letter_digit), Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
if (newPassword != confirmPassword) {
|
||||
Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, getString(R.string.password_mismatch), Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
isLoading = true
|
||||
binding.btnNext.isEnabled = false
|
||||
binding.btnNext.text = "重置中..."
|
||||
val loadingDialog = LoadingDialog(this)
|
||||
.setMessage(getString(R.string.resetting))
|
||||
.apply { show() }
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
@@ -175,8 +182,9 @@ class ForgetPasswordActivity : AppCompatActivity() {
|
||||
)
|
||||
val response = RetrofitNetwork.getNetworkService().forgotPassword(forgotRequest)
|
||||
withContext(Dispatchers.Main) {
|
||||
isLoading = false
|
||||
loadingDialog.dismiss()
|
||||
binding.btnNext.isEnabled = true
|
||||
binding.btnNext.text = "确定"
|
||||
|
||||
if (response.code == 200) {
|
||||
Toast.makeText(this@ForgetPasswordActivity, R.string.reset_success, Toast.LENGTH_SHORT).show()
|
||||
@@ -187,8 +195,9 @@ class ForgetPasswordActivity : AppCompatActivity() {
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
isLoading = false
|
||||
loadingDialog.dismiss()
|
||||
binding.btnNext.isEnabled = true
|
||||
binding.btnNext.text = "确定"
|
||||
Toast.makeText(this@ForgetPasswordActivity, R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,23 @@
|
||||
package com.example.defenseapplication.login
|
||||
package com.ckkj.defense_device.login
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import bean.LoginRequest
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.ActivityLoginBinding
|
||||
import com.example.defenseapplication.home.HomeActivity
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.utils.UserinfoUtil
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.databinding.ActivityLoginBinding
|
||||
import com.ckkj.defense_device.home.HomeActivity
|
||||
import com.ckkj.defense_device.utils.ApiConfig
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.utils.UserinfoUtil
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -26,19 +28,13 @@ class LoginActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityLoginBinding
|
||||
private var currentLoginMode = LoginMode.SMS
|
||||
private var countDownTimer: CountDownTimer? = null
|
||||
|
||||
enum class LoginMode { SMS, PASSWORD }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (UserinfoUtil.getUserInfo() != null) {
|
||||
val intent = Intent(this, HomeActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
finish()
|
||||
return
|
||||
}
|
||||
ApiConfig.resetAuthRedirectFlag()
|
||||
|
||||
binding = ActivityLoginBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
@@ -81,7 +77,7 @@ class LoginActivity : AppCompatActivity() {
|
||||
|
||||
binding.registerText.visibility = View.VISIBLE
|
||||
binding.forgetText.visibility = View.GONE
|
||||
updateRegisterTextConstraints(center = false)
|
||||
updateRegisterTextConstraints(center = true)
|
||||
|
||||
//需要正确的方法名和参数
|
||||
updateLoginButtonTopConstraint(R.id.smsRowLayout)
|
||||
@@ -106,7 +102,6 @@ class LoginActivity : AppCompatActivity() {
|
||||
private fun updateLoginButtonTopConstraint(topTargetId: Int) {
|
||||
val params = binding.loginBtn.layoutParams as ConstraintLayout.LayoutParams
|
||||
params.topToBottom = topTargetId
|
||||
params.topMargin = 32
|
||||
binding.loginBtn.layoutParams = params
|
||||
}
|
||||
|
||||
@@ -123,7 +118,6 @@ class LoginActivity : AppCompatActivity() {
|
||||
params.endToEnd = ConstraintSet.UNSET
|
||||
}
|
||||
params.topToBottom = binding.loginBtn.id
|
||||
params.topMargin = 20
|
||||
binding.registerText.layoutParams = params
|
||||
}
|
||||
|
||||
@@ -174,25 +168,24 @@ class LoginActivity : AppCompatActivity() {
|
||||
binding.registerText.setOnClickListener {
|
||||
val intent= Intent(this, RegisterActivity::class.java)
|
||||
startActivity(intent)
|
||||
Toast.makeText(this, R.string.redirect_register_page, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
binding.forgetText.setOnClickListener {
|
||||
val intent= Intent(this, ForgetPasswordActivity::class.java)
|
||||
startActivity(intent)
|
||||
Toast.makeText(this, R.string.forgot_password_page, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun startCountDown() {
|
||||
binding.sendCodeBtn.isEnabled = false
|
||||
object : CountDownTimer(60000, 1000) {
|
||||
countDownTimer = object : CountDownTimer(60000, 1000) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
binding.sendCodeBtn.text = getString(R.string.countdown_retry, millisUntilFinished / 1000)
|
||||
}
|
||||
override fun onFinish() {
|
||||
binding.sendCodeBtn.text = getString(R.string.send_code)
|
||||
binding.sendCodeBtn.text = getString(R.string.resend_code)
|
||||
binding.sendCodeBtn.isEnabled = true
|
||||
countDownTimer = null
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
@@ -226,9 +219,7 @@ class LoginActivity : AppCompatActivity() {
|
||||
phonenumber = phone,
|
||||
smsCode = smsCode
|
||||
)
|
||||
android.util.Log.d("LoginActivity", "短信登录请求: $loginRequest")
|
||||
val response = RetrofitNetwork.getNetworkService().login(loginRequest)
|
||||
android.util.Log.d("LoginActivity", "短信登录响应: code=${response.code}, msg=${response.msg}")
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200 && response.data != null) {
|
||||
UserinfoUtil.saveUserInfo(response.data)
|
||||
@@ -242,7 +233,6 @@ class LoginActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("LoginActivity", "短信登录异常", e)
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast.makeText(this@LoginActivity, R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
@@ -259,14 +249,13 @@ class LoginActivity : AppCompatActivity() {
|
||||
phonenumber = phone,
|
||||
password = password
|
||||
)
|
||||
android.util.Log.d("LoginActivity", "密码登录请求: $loginRequest")
|
||||
val response = RetrofitNetwork.getNetworkService().login(loginRequest)
|
||||
android.util.Log.d("LoginActivity", "密码登录响应: code=${response.code}, msg=${response.msg}")
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200 && response.data != null) {
|
||||
UserinfoUtil.saveUserInfo(response.data)
|
||||
Toast.makeText(this@LoginActivity, R.string.password_login_success_title, Toast.LENGTH_SHORT).show()
|
||||
val intent = Intent(this@LoginActivity, HomeActivity::class.java)
|
||||
//清除任务栈
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
finish()
|
||||
@@ -275,7 +264,6 @@ class LoginActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("LoginActivity", "密码登录异常", e)
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast.makeText(this@LoginActivity, R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
@@ -293,4 +281,10 @@ class LoginActivity : AppCompatActivity() {
|
||||
gradientDrawable.gradientType = GradientDrawable.LINEAR_GRADIENT
|
||||
view.background = gradientDrawable
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
countDownTimer?.cancel()
|
||||
countDownTimer = null
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.login
|
||||
package com.ckkj.defense_device.login
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
@@ -8,9 +8,10 @@ import android.os.CountDownTimer
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import bean.RegisterRequest
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.RegisterActivityBinding
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.databinding.RegisterActivityBinding
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.LoadingDialog
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -80,7 +81,7 @@ class RegisterActivity : AppCompatActivity() {
|
||||
val response = RetrofitNetwork.getNetworkService().getCode(userName)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200) {
|
||||
Toast.makeText(this@RegisterActivity, "验证码已发送", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this@RegisterActivity, R.string.code_already_sent, Toast.LENGTH_SHORT).show()
|
||||
startCountDown()
|
||||
} else {
|
||||
Toast.makeText(this@RegisterActivity, response.msg, Toast.LENGTH_SHORT).show()
|
||||
@@ -99,11 +100,10 @@ class RegisterActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun startCountDown() {
|
||||
binding.sendCodeBtn.isEnabled = false
|
||||
countDownTimer = object : CountDownTimer(COUNTDOWN_DURATION, COUNTDOWN_INTERVAL) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
val secondsRemaining = (millisUntilFinished / 1000).toInt()
|
||||
binding.sendCodeBtn.text = "${secondsRemaining}秒后重试"
|
||||
binding.sendCodeBtn.isEnabled = false
|
||||
binding.sendCodeBtn.text = getString(R.string.countdown_retry, millisUntilFinished / 1000)
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
@@ -115,7 +115,7 @@ class RegisterActivity : AppCompatActivity() {
|
||||
private fun resetSendButton() {
|
||||
countDownTimer?.cancel()
|
||||
countDownTimer = null
|
||||
binding.sendCodeBtn.text = getString(R.string.send_code)
|
||||
binding.sendCodeBtn.text = getString(R.string.resend_code)
|
||||
binding.sendCodeBtn.isEnabled = true
|
||||
isSendingCode = false
|
||||
}
|
||||
@@ -158,7 +158,9 @@ class RegisterActivity : AppCompatActivity() {
|
||||
|
||||
isLoading = true
|
||||
binding.btnNext.isEnabled = false
|
||||
binding.btnNext.text = getString(R.string.registering)
|
||||
val loadingDialog = LoadingDialog(this)
|
||||
.setMessage(getString(R.string.registering))
|
||||
.apply { show() }
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
@@ -174,12 +176,13 @@ class RegisterActivity : AppCompatActivity() {
|
||||
val response = RetrofitNetwork.getNetworkService().register(registerRequest)
|
||||
withContext(Dispatchers.Main) {
|
||||
isLoading = false
|
||||
loadingDialog.dismiss()
|
||||
binding.btnNext.isEnabled = true
|
||||
binding.btnNext.text = getString(R.string.next_step)
|
||||
|
||||
if (response.code == 200) {
|
||||
Toast.makeText(this@RegisterActivity, R.string.register_success, Toast.LENGTH_SHORT).show()
|
||||
val intent = Intent(this@RegisterActivity, LoginActivity::class.java)
|
||||
val intent = Intent(this@RegisterActivity, RegisterSuccessActivity::class.java)
|
||||
//清除任务栈
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
finish()
|
||||
@@ -190,8 +193,8 @@ class RegisterActivity : AppCompatActivity() {
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
isLoading = false
|
||||
loadingDialog.dismiss()
|
||||
binding.btnNext.isEnabled = true
|
||||
binding.btnNext.text = getString(R.string.next_step)
|
||||
Toast.makeText(this@RegisterActivity, R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,11 @@
|
||||
package com.example.defenseapplication.login
|
||||
package com.ckkj.defense_device.login
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.RegisterSuccessActivityBinding
|
||||
import com.example.defenseapplication.home.HomeActivity
|
||||
import com.ckkj.defense_device.databinding.RegisterSuccessActivityBinding
|
||||
import com.ckkj.defense_device.home.HomeActivity
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
//注册成功界面
|
||||
class RegisterSuccessActivity : AppCompatActivity() {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.model
|
||||
package com.ckkj.defense_device.model
|
||||
|
||||
data class FamilyItem(
|
||||
val id: String,
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.ckkj.defense_device.personal
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.databinding.CancelAccountActivityBinding
|
||||
import com.ckkj.defense_device.login.LoginActivity
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.utils.UserinfoUtil
|
||||
import com.ckkj.defense_device.view.CustomDialogFragment
|
||||
import com.ckkj.defense_device.view.DefenseDialogs
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class CancelAccountActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: CancelAccountActivityBinding
|
||||
private var countDownTimer: CountDownTimer? = null
|
||||
private var phoneNumber: String = ""
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = CancelAccountActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
ImmersionBar.with(this)
|
||||
.statusBarDarkFont(true)
|
||||
.titleBar(binding.topBar)
|
||||
.init()
|
||||
|
||||
getUserInfo()
|
||||
initListener()
|
||||
}
|
||||
|
||||
private fun getUserInfo() {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().getUserInfo()
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200 && response.data != null) {
|
||||
phoneNumber = response.data?.phonenumber ?: ""
|
||||
binding.tvPhoneNumber.text = maskPhoneNumber(phoneNumber)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast.makeText(this@CancelAccountActivity, R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun maskPhoneNumber(phone: String): String {
|
||||
if (phone.length != 11) {
|
||||
return phone
|
||||
}
|
||||
return phone.substring(0, 3) + "****" + phone.substring(7)
|
||||
}
|
||||
|
||||
private fun initListener() {
|
||||
binding.ivBack.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
binding.btnSendCode.setOnClickListener {
|
||||
if (phoneNumber.isEmpty()) {
|
||||
Toast.makeText(this, R.string.get_user_info_fail, Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (phoneNumber.length != 11) {
|
||||
Toast.makeText(this, R.string.phone_format_invalid, Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
sendVerificationCode(phoneNumber)
|
||||
}
|
||||
|
||||
binding.btnCancelAccount.setOnClickListener {
|
||||
DefenseDialogs.showDialog(
|
||||
this,
|
||||
config = CustomDialogFragment.Config(
|
||||
title = getString(R.string.tip),
|
||||
message = getString(R.string.confirm_cancel_account_user_account),
|
||||
positiveText = getString(R.string.confirm),
|
||||
negativeText = getString(R.string.cancel)
|
||||
),
|
||||
onPositiveClick = {
|
||||
Toast.makeText(this@CancelAccountActivity, getString(R.string.cancel_account), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendVerificationCode(phone: String) {
|
||||
binding.btnSendCode.isEnabled = false
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().getCode(phone)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200) {
|
||||
Toast.makeText(this@CancelAccountActivity, getString(R.string.code_sent_to, phone), Toast.LENGTH_SHORT).show()
|
||||
startCountdown()
|
||||
} else {
|
||||
binding.btnSendCode.isEnabled = true
|
||||
Toast.makeText(this@CancelAccountActivity, response.msg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.btnSendCode.isEnabled = true
|
||||
Toast.makeText(this@CancelAccountActivity, R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun startCountdown() {
|
||||
countDownTimer = object : CountDownTimer(60000, 1000) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
binding.btnSendCode.text = getString(R.string.countdown_retry, millisUntilFinished / 1000)
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
binding.btnSendCode.text = getString(R.string.resend_code)
|
||||
binding.btnSendCode.isEnabled = true
|
||||
countDownTimer = null
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
countDownTimer?.cancel()
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.example.defenseapplication.personal
|
||||
package com.ckkj.defense_device.personal
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.bean.UpdatePassword
|
||||
import com.example.defenseapplication.databinding.ChangePasswordActivityBinding
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.bean.UpdatePassword
|
||||
import com.ckkj.defense_device.databinding.ChangePasswordActivityBinding
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.example.defenseapplication.personal
|
||||
package com.ckkj.defense_device.personal
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.databinding.FaceManagementActivityBinding
|
||||
import com.example.defenseapplication.login.FaceLoginActivity
|
||||
import com.ckkj.defense_device.databinding.FaceManagementActivityBinding
|
||||
import com.ckkj.defense_device.login.FaceLoginActivity
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
|
||||
//人脸管理页面
|
||||
@@ -1,32 +1,45 @@
|
||||
package com.example.defenseapplication.personal
|
||||
package com.ckkj.defense_device.personal
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.bean.VerifyOptionPasswordRequest
|
||||
import com.example.defenseapplication.databinding.DialogExpireTimeBinding
|
||||
import com.example.defenseapplication.databinding.InvitationCodeActivityBinding
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.bean.RecommendationCodeBean
|
||||
import com.ckkj.defense_device.bean.SelectInviterInfoBean
|
||||
import com.ckkj.defense_device.bean.VerifyOptionPasswordRequest
|
||||
import com.ckkj.defense_device.databinding.DialogExpireTimeBinding
|
||||
import com.ckkj.defense_device.databinding.InvitationCodeActivityBinding
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.LoadingDialog
|
||||
import com.google.gson.Gson
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import com.google.zxing.EncodeHintType
|
||||
import com.google.zxing.qrcode.QRCodeWriter
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.maning.mlkitscanner.scan.MNScanManager
|
||||
import com.maning.mlkitscanner.scan.callback.act.MNScanCallback
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.Hashtable
|
||||
@@ -44,7 +57,24 @@ class InvitationCodeActivity : AppCompatActivity() {
|
||||
private var isLoading = false // 是否正在加载
|
||||
private var hasGeneratedQrCode = false // 是否已经生成过二维码
|
||||
|
||||
private val requestPermissionsLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.RequestMultiplePermissions()
|
||||
) { permissions ->
|
||||
val cameraGranted = permissions[Manifest.permission.CAMERA] ?: false
|
||||
val storageGranted = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
permissions[Manifest.permission.READ_MEDIA_IMAGES] ?: false
|
||||
} else {
|
||||
permissions[Manifest.permission.READ_EXTERNAL_STORAGE] ?: false
|
||||
}
|
||||
if (cameraGranted && storageGranted) {
|
||||
startScan()
|
||||
} else {
|
||||
Toast.makeText(this, R.string.permission_denied, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "InvitationCodeActivity"
|
||||
const val EXPIRE_24H = 24 * 60 * 60 * 1000L
|
||||
const val EXPIRE_7D = 7 * 24 * 60 * 60 * 1000L
|
||||
}
|
||||
@@ -90,15 +120,136 @@ class InvitationCodeActivity : AppCompatActivity() {
|
||||
|
||||
// 撤销邀请按钮
|
||||
binding.btnCancelInvite.setOnClickListener {
|
||||
showPasswordDialog {
|
||||
cancelInvitation()
|
||||
if (generatedInviteCode.isEmpty()) {
|
||||
ToastUtils.showError(this, getString(R.string.qr_code_expired))
|
||||
return@setOnClickListener
|
||||
}
|
||||
showPasswordDialog { password, dialog ->
|
||||
cancelInvitation(password, dialog)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成/重新生成按钮
|
||||
binding.btnRegenerate.setOnClickListener {
|
||||
showPasswordDialog {
|
||||
generateOrRegenerateInvitation()
|
||||
showPasswordDialog { password, dialog ->
|
||||
generateOrRegenerateInvitation(password, dialog)
|
||||
}
|
||||
}
|
||||
binding.sys.setOnClickListener {
|
||||
checkPermissionsAndScan()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPermissionsAndScan() {
|
||||
val cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
|
||||
val storagePermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES)
|
||||
} else {
|
||||
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
if (cameraPermission == PackageManager.PERMISSION_GRANTED &&
|
||||
storagePermission == PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
startScan()
|
||||
} else {
|
||||
val permissionsToRequest = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
arrayOf(
|
||||
Manifest.permission.CAMERA,
|
||||
Manifest.permission.READ_MEDIA_IMAGES
|
||||
)
|
||||
} else {
|
||||
arrayOf(
|
||||
Manifest.permission.CAMERA,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
)
|
||||
}
|
||||
requestPermissionsLauncher.launch(permissionsToRequest)
|
||||
}
|
||||
}
|
||||
|
||||
private fun startScan() {
|
||||
MNScanManager.startScan(this, object : MNScanCallback {
|
||||
override fun onActivityResult(resultCode: Int, data: Intent?) {
|
||||
when (resultCode) {
|
||||
MNScanManager.RESULT_SUCCESS -> {
|
||||
val result = data?.getStringArrayListExtra(MNScanManager.INTENT_KEY_RESULT_SUCCESS)
|
||||
if (!result.isNullOrEmpty()) {
|
||||
val inviteCode = parseInviteCode(result[0])
|
||||
if (inviteCode.isNullOrEmpty()) {
|
||||
Toast.makeText(this@InvitationCodeActivity, "无效的邀请码", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
fetchInviterInfo(inviteCode)
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this@InvitationCodeActivity, "扫码结果为空", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
MNScanManager.RESULT_FAIL -> {
|
||||
val error = data?.getStringExtra(MNScanManager.INTENT_KEY_RESULT_ERROR)
|
||||
Toast.makeText(this@InvitationCodeActivity, "扫码失败: $error", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
MNScanManager.RESULT_CANCLE -> {
|
||||
Toast.makeText(this@InvitationCodeActivity, "扫码取消", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun parseInviteCode(scanResult: String): String? {
|
||||
val trimmed = scanResult.trim()
|
||||
if (trimmed.isEmpty()) return null
|
||||
return try {
|
||||
if (trimmed.startsWith("{")) {
|
||||
JSONObject(trimmed).optString("code").takeIf { it.isNotEmpty() }
|
||||
} else {
|
||||
trimmed
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
trimmed
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchInviterInfo(inviteCode: String) {
|
||||
val loadingDialog = LoadingDialog(this).apply { show() }
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService()
|
||||
.selectInviterInfo(SelectInviterInfoBean(code = inviteCode))
|
||||
withContext(Dispatchers.Main) {
|
||||
loadingDialog.dismiss()
|
||||
if (response.code == 200 && response.data != null) {
|
||||
val inviter = response.data
|
||||
val parentId = inviter.resolveParentId()
|
||||
if (parentId.isNullOrEmpty()) {
|
||||
Toast.makeText(
|
||||
this@InvitationCodeActivity,
|
||||
getString(R.string.network_error),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
return@withContext
|
||||
}
|
||||
val intent = Intent(this@InvitationCodeActivity, JoinFamilyInviteActivity::class.java).apply {
|
||||
putExtra(JoinFamilyInviteActivity.EXTRA_INVITE_CODE, inviteCode)
|
||||
putExtra(JoinFamilyInviteActivity.EXTRA_NICK_NAME, inviter.nickName)
|
||||
putExtra(JoinFamilyInviteActivity.EXTRA_AVATAR, inviter.avatar)
|
||||
putExtra(JoinFamilyInviteActivity.EXTRA_PARENT_ID, parentId)
|
||||
putExtra(JoinFamilyInviteActivity.EXTRA_USER_ID, inviter.userId)
|
||||
}
|
||||
startActivity(intent)
|
||||
} else {
|
||||
Toast.makeText(
|
||||
this@InvitationCodeActivity,
|
||||
response.msg.ifBlank { getString(R.string.network_error) },
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
loadingDialog.dismiss()
|
||||
Toast.makeText(this@InvitationCodeActivity, R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,14 +257,56 @@ class InvitationCodeActivity : AppCompatActivity() {
|
||||
/**
|
||||
* 生成或重新生成邀请码
|
||||
*/
|
||||
private fun generateOrRegenerateInvitation() {
|
||||
// 根据当前选择的时效生成邀请码
|
||||
private fun generateOrRegenerateInvitation(password: String, passwordDialog: PasswordInputDialog) {
|
||||
if (isLoading) return
|
||||
isLoading = true
|
||||
val loadingDialog = LoadingDialog(this).apply { show() }
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService()
|
||||
.generateRecommendationCode(VerifyOptionPasswordRequest(password))
|
||||
Log.d(TAG, "生成推荐码响应: code=${response.code}, msg=${response.msg}, data=${response.data}")
|
||||
withContext(Dispatchers.Main) {
|
||||
isLoading = false
|
||||
loadingDialog.dismiss()
|
||||
if (response.code == 200) {
|
||||
val parsed = parseRecommendationCode(response.data)
|
||||
if (parsed != null) {
|
||||
passwordDialog.dismiss()
|
||||
generatedInviteCode = parsed.first
|
||||
expireTimestamp = parsed.second
|
||||
qrCodeContent =
|
||||
"{\"type\":\"invite\",\"code\":\"$generatedInviteCode\",\"expire\":$expireTimestamp}"
|
||||
Log.d(
|
||||
TAG,
|
||||
"推荐码生成成功: Code=$generatedInviteCode, expireTimestamp=$expireTimestamp, qrContent=$qrCodeContent"
|
||||
)
|
||||
generateQRCode()
|
||||
showQrCode()
|
||||
// 更新按钮文字为"重新生成"
|
||||
binding.btnRegenerate.text = getString(R.string.regenerate)
|
||||
hasGeneratedQrCode = true
|
||||
ToastUtils.showSuccess(this, getString(R.string.operation_success))
|
||||
ToastUtils.showSuccess(this@InvitationCodeActivity, getString(R.string.operation_success))
|
||||
} else {
|
||||
Log.w(TAG, "推荐码解析失败, raw data=${response.data}")
|
||||
passwordDialog.showError(getString(R.string.network_error))
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "生成推荐码失败: code=${response.code}, msg=${response.msg}")
|
||||
passwordDialog.showError(
|
||||
response.msg.ifEmpty { getString(R.string.password_error) }
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "生成推荐码异常", e)
|
||||
withContext(Dispatchers.Main) {
|
||||
isLoading = false
|
||||
loadingDialog.dismiss()
|
||||
passwordDialog.showError(getString(R.string.network_error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showExpireTimeDialog() {
|
||||
@@ -151,9 +344,6 @@ class InvitationCodeActivity : AppCompatActivity() {
|
||||
binding.tvExpireTime.text = getString(R.string.expire_7d)
|
||||
}
|
||||
}
|
||||
// 显示二维码并生成
|
||||
showQrCode()
|
||||
generateQRCode()
|
||||
expireTimeDialog?.dismiss()
|
||||
}
|
||||
|
||||
@@ -173,22 +363,28 @@ class InvitationCodeActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun generateQRCode() {
|
||||
// 检查二维码是否过期,如果过期则生成新的邀请码
|
||||
val isExpired = expireTimestamp > 0 && System.currentTimeMillis() > expireTimestamp
|
||||
val content = if (qrCodeContent.isNotEmpty() && !isExpired) qrCodeContent else generateInviteCode()
|
||||
val qrBitmap = createQRCodeWithLogo(content, 400, 400)
|
||||
if (qrCodeContent.isEmpty()) return
|
||||
val qrBitmap = createQRCodeWithLogo(qrCodeContent, 400, 400)
|
||||
binding.ivQrCode.setImageBitmap(qrBitmap)
|
||||
}
|
||||
|
||||
private fun generateInviteCode(): String {
|
||||
val timestamp = System.currentTimeMillis()
|
||||
expireTimestamp = timestamp + expireTimeInMillis
|
||||
generatedInviteCode = "INV${timestamp}"
|
||||
qrCodeContent = "{\"type\":\"invite\",\"code\":\"$generatedInviteCode\",\"expire\":$expireTimestamp}"
|
||||
// 输出日志,方便调试验证
|
||||
android.util.Log.d("InvitationCode", "生成的二维码内容: $qrCodeContent")
|
||||
android.util.Log.d("InvitationCode", "推荐码: $generatedInviteCode, 过期时间戳: $expireTimestamp")
|
||||
return qrCodeContent
|
||||
private fun parseRecommendationCode(data: Any?): Pair<String, Long>? {
|
||||
if (data == null) return null
|
||||
return when (data) {
|
||||
is String -> {
|
||||
if (data.isEmpty()) null
|
||||
else Pair(data, System.currentTimeMillis() + expireTimeInMillis)
|
||||
}
|
||||
else -> {
|
||||
val bean = Gson().fromJson(Gson().toJson(data), RecommendationCodeBean::class.java)
|
||||
val code = bean.inviteCode?.takeIf { it.isNotEmpty() }
|
||||
?: bean.code?.takeIf { it.isNotEmpty() }
|
||||
?: return null
|
||||
val expire = bean.expireTime ?: bean.expire
|
||||
?: (System.currentTimeMillis() + expireTimeInMillis)
|
||||
Pair(code, expire)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 这段代码生成带Logo的二维码:
|
||||
@@ -232,7 +428,7 @@ class InvitationCodeActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
val logoDrawable = ContextCompat.getDrawable(this, R.mipmap.loge)
|
||||
val logoDrawable = ContextCompat.getDrawable(this, R.mipmap.logo)
|
||||
if (logoDrawable != null) {
|
||||
val logoSize = width / 5
|
||||
val logoX = (width - logoSize) / 2
|
||||
@@ -415,55 +611,61 @@ class InvitationCodeActivity : AppCompatActivity() {
|
||||
/**
|
||||
* 撤销邀请
|
||||
*/
|
||||
private fun cancelInvitation() {
|
||||
// 撤销邀请逻辑
|
||||
private fun cancelInvitation(password: String, passwordDialog: PasswordInputDialog) {
|
||||
if (isLoading) return
|
||||
if (generatedInviteCode.isEmpty()) {
|
||||
passwordDialog.showError(getString(R.string.qr_code_expired))
|
||||
return
|
||||
}
|
||||
isLoading = true
|
||||
val loadingDialog = LoadingDialog(this).apply { show() }
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService()
|
||||
.revokeInvitation(VerifyOptionPasswordRequest(password))
|
||||
Log.d(TAG, "撤销邀请响应: code=${response.code}, msg=${response.msg}")
|
||||
withContext(Dispatchers.Main) {
|
||||
isLoading = false
|
||||
loadingDialog.dismiss()
|
||||
if (response.code == 200) {
|
||||
passwordDialog.dismiss()
|
||||
hideQrCode()
|
||||
generatedInviteCode = ""
|
||||
qrCodeContent = ""
|
||||
expireTimestamp = 0
|
||||
hasGeneratedQrCode = false
|
||||
// 恢复按钮文字为"生成邀请码"
|
||||
binding.btnRegenerate.text = getString(R.string.generate_invite_code)
|
||||
// 显示提示
|
||||
ToastUtils.showSuccess(this, getString(R.string.operation_success))
|
||||
ToastUtils.showSuccess(this@InvitationCodeActivity, getString(R.string.operation_success))
|
||||
} else {
|
||||
passwordDialog.showError(
|
||||
response.msg.ifEmpty { getString(R.string.password_error) }
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "撤销邀请异常", e)
|
||||
withContext(Dispatchers.Main) {
|
||||
isLoading = false
|
||||
loadingDialog.dismiss()
|
||||
passwordDialog.showError(getString(R.string.network_error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示密码输入对话框
|
||||
* @param onSuccess 验证成功后的回调
|
||||
*/
|
||||
private fun showPasswordDialog(onSuccess: () -> Unit) {
|
||||
private fun showPasswordDialog(onConfirm: (String, PasswordInputDialog) -> Unit) {
|
||||
val dialog = PasswordInputDialog(this)
|
||||
dialog.setTitle(getString(R.string.input_op_pwd))
|
||||
dialog.setOnConfirmListener { password ->
|
||||
verifyPassword(password, dialog, onSuccess)
|
||||
onConfirm(password, dialog)
|
||||
}
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证操作密码
|
||||
*/
|
||||
private fun verifyPassword(password: String, dialog: PasswordInputDialog, onSuccess: () -> Unit) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService()
|
||||
.verifyOptionPassword(VerifyOptionPasswordRequest(password))
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200) {
|
||||
dialog.dismiss()
|
||||
onSuccess.invoke()
|
||||
} else {
|
||||
dialog.showError(getString(R.string.password_error))
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
dialog.showError(getString(R.string.network_error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.ckkj.defense_device.personal
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.bean.JoinTheFamilyBean
|
||||
import com.ckkj.defense_device.databinding.JoinFamilyInviteActivityBinding
|
||||
import com.ckkj.defense_device.home.HomeActivity
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.LoadingDialog
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
// 邀请加入家庭
|
||||
class JoinFamilyInviteActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: JoinFamilyInviteActivityBinding
|
||||
private var isLoading = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = JoinFamilyInviteActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
ImmersionBar.with(this)
|
||||
.statusBarDarkFont(true)
|
||||
.titleBar(binding.topBar)
|
||||
.init()
|
||||
|
||||
binding.ivBack.setOnClickListener { finish() }
|
||||
binding.btnJoinNow.setOnClickListener { joinFamily() }
|
||||
displayInviterInfo()
|
||||
}
|
||||
|
||||
private fun joinFamily() {
|
||||
if (isLoading) return
|
||||
|
||||
val parentId = intent.getStringExtra(EXTRA_USER_ID).orEmpty()
|
||||
val inviteCode = intent.getStringExtra(EXTRA_INVITE_CODE).orEmpty()
|
||||
if (parentId.isEmpty() || inviteCode.isEmpty()) {
|
||||
Log.e(TAG, "加入家庭参数无效: parentId=$parentId, inviteCode=$inviteCode")
|
||||
Toast.makeText(this, R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
Log.e(TAG, "加入家庭请求: parentId=$parentId, inviteCode=$inviteCode")
|
||||
isLoading = true
|
||||
val loadingDialog = LoadingDialog(this).apply { show() }
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService()
|
||||
.joinTheFamily(JoinTheFamilyBean(parentId = parentId, inviteCode = inviteCode))
|
||||
Log.e(TAG, "加入家庭响应: code=${response.code}, msg=${response.msg}, data=${response.data}")
|
||||
withContext(Dispatchers.Main) {
|
||||
isLoading = false
|
||||
loadingDialog.dismiss()
|
||||
if (response.code == 200) {
|
||||
Log.e(TAG, "加入家庭成功,返回首页刷新")
|
||||
ToastUtils.showSuccess(this@JoinFamilyInviteActivity, getString(R.string.operation_success))
|
||||
val homeIntent = Intent(this@JoinFamilyInviteActivity, HomeActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
putExtra(HomeActivity.EXTRA_REFRESH, true)
|
||||
}
|
||||
startActivity(homeIntent)
|
||||
finish()
|
||||
} else {
|
||||
Log.e(TAG, "加入家庭失败: code=${response.code}, msg=${response.msg}")
|
||||
Toast.makeText(
|
||||
this@JoinFamilyInviteActivity,
|
||||
response.msg.ifBlank { getString(R.string.network_error) },
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "加入家庭请求异常", e)
|
||||
withContext(Dispatchers.Main) {
|
||||
isLoading = false
|
||||
loadingDialog.dismiss()
|
||||
Toast.makeText(this@JoinFamilyInviteActivity, R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayInviterInfo() {
|
||||
val nickName = intent.getStringExtra(EXTRA_NICK_NAME).orEmpty()
|
||||
val avatar = intent.getStringExtra(EXTRA_AVATAR)
|
||||
|
||||
binding.tvNickname.text = nickName.ifEmpty { getString(R.string.nickname_placeholder) }
|
||||
binding.tvInviteMessage.text = getString(
|
||||
R.string.invite_join_family_message,
|
||||
nickName.ifEmpty { getString(R.string.nickname_placeholder) }
|
||||
)
|
||||
|
||||
val requestOptions = RequestOptions()
|
||||
.placeholder(R.mipmap.img)
|
||||
.error(R.mipmap.img)
|
||||
|
||||
Glide.with(this)
|
||||
.load(avatar)
|
||||
.apply(requestOptions)
|
||||
.circleCrop()
|
||||
.into(binding.ivAvatar)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "JoinFamilyInviteActivity"
|
||||
const val EXTRA_INVITE_CODE = "invite_code"
|
||||
const val EXTRA_NICK_NAME = "nick_name"
|
||||
const val EXTRA_AVATAR = "avatar"
|
||||
const val EXTRA_PARENT_ID = "parent_id"
|
||||
const val EXTRA_USER_ID = "user_id"
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,9 @@
|
||||
package com.example.defenseapplication.personal
|
||||
package com.ckkj.defense_device.personal
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.LoginPasswordActivityBinding
|
||||
import com.example.defenseapplication.databinding.PasswordManagementActivityBinding
|
||||
import com.ckkj.defense_device.databinding.LoginPasswordActivityBinding
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
|
||||
//登录密码
|
||||
@@ -1,16 +1,16 @@
|
||||
package com.example.defenseapplication.personal
|
||||
package com.ckkj.defense_device.personal
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.bean.UpdateUserInfo
|
||||
import com.example.defenseapplication.bean.VerifyOptionPasswordRequest
|
||||
import com.example.defenseapplication.databinding.OperationPasswordActivityBinding
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.view.CustomDialogFragment
|
||||
import com.example.defenseapplication.view.LoadingDialog
|
||||
import com.example.defenseapplication.view.showDefenseDialog
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.bean.UpdateUserInfo
|
||||
import com.ckkj.defense_device.bean.VerifyOptionPasswordRequest
|
||||
import com.ckkj.defense_device.databinding.OperationPasswordActivityBinding
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.CustomDialogFragment
|
||||
import com.ckkj.defense_device.view.LoadingDialog
|
||||
import com.ckkj.defense_device.view.showDefenseDialog
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.example.defenseapplication.personal
|
||||
package com.ckkj.defense_device.personal
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.databinding.PasswordManagementActivityBinding
|
||||
import com.ckkj.defense_device.databinding.PasswordManagementActivityBinding
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
//密码管理
|
||||
class PasswordManagementActivity : AppCompatActivity() {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.personal
|
||||
package com.ckkj.defense_device.personal
|
||||
|
||||
import android.Manifest
|
||||
import android.content.ContentResolver
|
||||
@@ -11,24 +11,21 @@ import android.os.Environment
|
||||
import android.provider.MediaStore
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.bean.UpdateUserInfo
|
||||
import com.example.defenseapplication.bean.UserInfoBean
|
||||
import com.example.defenseapplication.databinding.PersonalProfileActivityBinding
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.example.defenseapplication.view.AvatarSelectDialog
|
||||
import com.example.defenseapplication.view.CustomDialogFragmentText
|
||||
import com.example.defenseapplication.view.LoadingDialog
|
||||
import com.example.defenseapplication.view.PhoneModifyDialogFragment
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.bean.UpdateUserInfo
|
||||
import com.ckkj.defense_device.bean.UserInfoBean
|
||||
import com.ckkj.defense_device.databinding.PersonalProfileActivityBinding
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.view.AvatarSelectDialog
|
||||
import com.ckkj.defense_device.view.CustomDialogFragmentText
|
||||
import com.ckkj.defense_device.view.LoadingDialog
|
||||
import com.ckkj.defense_device.view.PhoneModifyDialogFragment
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.example.defenseapplication.personal
|
||||
package com.ckkj.defense_device.personal
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import bean.ForgotRequest
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.RetrievePasswordActivityBinding
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.ckkj.defense_device.R
|
||||
import com.ckkj.defense_device.databinding.RetrievePasswordActivityBinding
|
||||
import com.ckkj.defense_device.utils.RetrofitNetwork
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -163,7 +163,7 @@ class RetrievePasswordActivity : AppCompatActivity() {
|
||||
override fun onFinish() {
|
||||
isCountingDown = false
|
||||
binding.btnGetCode.isEnabled = true
|
||||
binding.btnGetCode.text = getString(R.string.get_verification_code)
|
||||
binding.btnGetCode.text = getString(R.string.resend_code)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.ckkj.defense_device.personal
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.ckkj.defense_device.databinding.SettingsMenusActivityBinding
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import java.io.File
|
||||
|
||||
class SettingsMenusActivity : AppCompatActivity() {
|
||||
private lateinit var binding: SettingsMenusActivityBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = SettingsMenusActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
ImmersionBar.with(this)
|
||||
.statusBarDarkFont(true)
|
||||
.titleBar(binding.topBar)
|
||||
.init()
|
||||
|
||||
|
||||
val versionName = packageManager.getPackageInfo(packageName, 0).versionName
|
||||
binding.tvVersion.text = versionName
|
||||
// 显示缓存大小
|
||||
displayCacheSize()
|
||||
|
||||
setupClickListeners()
|
||||
}
|
||||
|
||||
private fun setupClickListeners() {
|
||||
// 返回按钮
|
||||
binding.ivBack.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
// 检查更新
|
||||
binding.itemCheckUpdate.setOnClickListener {
|
||||
Toast.makeText(this, "正在检查更新...", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
// 清除缓存
|
||||
binding.itemClearCache.setOnClickListener {
|
||||
clearCache()
|
||||
displayCacheSize() // 更新缓存大小显示
|
||||
Toast.makeText(this, "缓存已清除", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
// 用户协议
|
||||
binding.itemUserAgreement.setOnClickListener {
|
||||
|
||||
}
|
||||
|
||||
// 隐私政策
|
||||
binding.itemPrivacyPolicy.setOnClickListener {
|
||||
|
||||
}
|
||||
|
||||
// 注销账号
|
||||
binding.itemLogout.setOnClickListener {
|
||||
val intent = Intent(this, CancelAccountActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
//缓存方法
|
||||
private fun displayCacheSize() {
|
||||
val cacheSize = getCacheSize()
|
||||
val sizeString = when {
|
||||
cacheSize >= 1024 * 1024 -> String.format("%.2f MB", cacheSize / (1024.0 * 1024.0))
|
||||
else -> String.format("%d KB", cacheSize / 1024)
|
||||
}
|
||||
binding.tvCacheSize.text = sizeString
|
||||
}
|
||||
|
||||
private fun getCacheSize(): Long {
|
||||
val cacheDir = cacheDir
|
||||
return getFolderSize(cacheDir)
|
||||
}
|
||||
|
||||
private fun getFolderSize(dir: File?): Long {
|
||||
var size = 0L
|
||||
if (dir != null && dir.isDirectory) {
|
||||
dir.listFiles()?.forEach { file ->
|
||||
size += if (file.isFile) {
|
||||
file.length()
|
||||
} else {
|
||||
getFolderSize(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
private fun clearCache() {
|
||||
val cacheDir = cacheDir
|
||||
deleteDir(cacheDir)
|
||||
}
|
||||
|
||||
private fun deleteDir(dir: File?): Boolean {
|
||||
if (dir != null && dir.isDirectory) {
|
||||
dir.listFiles()?.forEach { file ->
|
||||
deleteDir(file)
|
||||
}
|
||||
}
|
||||
return dir?.delete() ?: false
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.defenseapplication.utils
|
||||
package com.ckkj.defense_device.utils
|
||||
|
||||
import android.app.Activity
|
||||
import java.lang.ref.WeakReference
|
||||
@@ -1,8 +1,14 @@
|
||||
package com.example.defenseapplication.utils
|
||||
package com.ckkj.defense_device.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import com.example.defenseapplication.bean.BaseInfo
|
||||
import android.widget.Toast
|
||||
import com.blankj.utilcode.util.Utils
|
||||
import com.ckkj.defense_device.bean.BaseInfo
|
||||
import com.ckkj.defense_device.login.LoginActivity
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonParser
|
||||
import okhttp3.Interceptor
|
||||
@@ -24,10 +30,17 @@ object ApiConfig {
|
||||
@Volatile
|
||||
public var authToken: String = ""
|
||||
|
||||
@Volatile
|
||||
private var isRedirectingToLogin = false
|
||||
|
||||
fun updateAuthToken(token: String) {
|
||||
authToken = token
|
||||
}
|
||||
|
||||
fun resetAuthRedirectFlag() {
|
||||
isRedirectingToLogin = false
|
||||
}
|
||||
|
||||
fun hasAuthToken(): Boolean {
|
||||
return authToken.isNotBlank()
|
||||
}
|
||||
@@ -116,8 +129,8 @@ object ApiConfig {
|
||||
val businessCode = if (jsonObject.has("code")) jsonObject.get("code").asInt else 0
|
||||
|
||||
if (httpCode == 401 || httpCode == 424 || businessCode == 401) {
|
||||
clearUserLoginInfo()
|
||||
val msg = if (jsonObject.has("msg")) jsonObject.get("msg").asString else "登录已过期,请重新登录"
|
||||
redirectToLogin(msg)
|
||||
return@Interceptor buildFakeErrorResponse(request, msg, code = if (businessCode != 0) businessCode else httpCode)
|
||||
}
|
||||
|
||||
@@ -138,7 +151,7 @@ object ApiConfig {
|
||||
*/
|
||||
private fun buildFakeErrorResponse(request: Request, msg: String, code: Int = 1): Response {
|
||||
val baseInfo = BaseInfo(
|
||||
message = msg,
|
||||
msg = msg,
|
||||
code = code,
|
||||
data = null,
|
||||
)
|
||||
@@ -179,12 +192,36 @@ object ApiConfig {
|
||||
private fun buildAuthorizationValue(token: String): String {
|
||||
return if (token.startsWith("Bearer ")) token else "Bearer $token"
|
||||
}
|
||||
//401跳转登录界面
|
||||
private fun redirectToLogin(msg: String) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
if (isRedirectingToLogin) return@post
|
||||
val current = ActivityManager.getCurrentActivity()
|
||||
if (current is LoginActivity) return@post
|
||||
|
||||
isRedirectingToLogin = true
|
||||
clearUserLoginInfo()
|
||||
|
||||
val context = current ?: Utils.getApp()
|
||||
ActivityManager.finishAllActivities()
|
||||
|
||||
val intent = Intent(context, LoginActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
context.startActivity(intent)
|
||||
|
||||
if (msg.isNotBlank()) {
|
||||
Toast.makeText(Utils.getApp(), msg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearUserLoginInfo() {
|
||||
try {
|
||||
authToken = ""
|
||||
UserinfoUtil.clearUserInfo()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
authToken = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user