From 2c2d2b0fac75b8d354222ea6f76cb9d2d1365b25 Mon Sep 17 00:00:00 2001
From: xiaowusky <chenyangyang3858@dingtalk.com>
Date: Thu, 29 Jun 2023 14:19:18 +0800
Subject: [PATCH] =?UTF-8?q?desc:=E4=BA=91=E5=B9=B3=E5=8F=B0=E6=95=B0?=
 =?UTF-8?q?=E6=8D=AE=E5=90=8C=E6=AD=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../java/com/yinuo/safetywatcher/TestUtils.kt |  22 +--
 .../watcher/base/BaseActivity.kt              |   6 +
 .../watcher/constant/Constants.kt             |   2 +-
 .../safetywatcher/watcher/net/DevicesApi.kt   |  23 ++-
 .../watcher/net/UploadFileApi.kt              |  18 +-
 .../safetywatcher/watcher/ui/CloudActivity.kt | 177 ++++++++++--------
 app/src/main/res/values/strings.xml           |   1 +
 .../com/common/commonlib/db/dao/VideoDao.kt   |   5 +-
 8 files changed, 135 insertions(+), 119 deletions(-)

diff --git a/app/src/main/java/com/yinuo/safetywatcher/TestUtils.kt b/app/src/main/java/com/yinuo/safetywatcher/TestUtils.kt
index c9829eb..506ead8 100644
--- a/app/src/main/java/com/yinuo/safetywatcher/TestUtils.kt
+++ b/app/src/main/java/com/yinuo/safetywatcher/TestUtils.kt
@@ -87,17 +87,17 @@ object TestUtils {
     }
 
     fun testUploadFile(uploadApi: UploadFileApi, video: Video, commonDialog: CommonDialog?) {
-        val path = video.path
-        uploadApi.singleUpload(path, System.currentTimeMillis(), object :
-            RequestResultCallBack<BaseResponse>() {
-            override fun onResult(result: BaseResponse) {
-                commonDialog?.dismiss()
-            }
-
-            override fun onError(error: String?) {
-                commonDialog?.dismiss()
-            }
-        })
+//        val path = video.path
+//        uploadApi.singleUpload(path, System.currentTimeMillis(), object :
+//            RequestResultCallBack<BaseResponse>() {
+//            override fun onResult(result: BaseResponse) {
+//                commonDialog?.dismiss()
+//            }
+//
+//            override fun onError(error: String?) {
+//                commonDialog?.dismiss()
+//            }
+//        })
     }
 
     fun testExportExcel(context: Context, datas: MutableList<Gas>, commonDialog: CommonDialog?) {
diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/base/BaseActivity.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/base/BaseActivity.kt
index 72c7cd0..eba4a5d 100644
--- a/app/src/main/java/com/yinuo/safetywatcher/watcher/base/BaseActivity.kt
+++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/base/BaseActivity.kt
@@ -77,6 +77,7 @@ abstract class BaseActivity : AppCompatActivity() {
 
     fun closeLoadingDialog() {
         loadingDialog?.dismiss()
+        loadingDialog = null
     }
 
     open val isHome: Boolean = false
@@ -132,4 +133,9 @@ abstract class BaseActivity : AppCompatActivity() {
     fun tryFocusBackArea() {
         baseBinding.topBar.tryFocusBackArea()
     }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        closeLoadingDialog()
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/constant/Constants.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/constant/Constants.kt
index d450d2f..7d09109 100644
--- a/app/src/main/java/com/yinuo/safetywatcher/watcher/constant/Constants.kt
+++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/constant/Constants.kt
@@ -21,4 +21,4 @@ const val DELAY_TIME_CHECK_CAMERA = 5
 const val NAMESPACE_ANDROID = "http://schemas.android.com/apk/res/android"
 
 // 云同步时,20条数据已上传
-const val GAS_CLOUD_UPLOAD_SIZE_ONCE = 20;
\ No newline at end of file
+const val GAS_CLOUD_UPLOAD_SIZE_ONCE = 20
\ No newline at end of file
diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/net/DevicesApi.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/net/DevicesApi.kt
index b4e0622..90e9192 100644
--- a/app/src/main/java/com/yinuo/safetywatcher/watcher/net/DevicesApi.kt
+++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/net/DevicesApi.kt
@@ -42,24 +42,23 @@ class DevicesApi : BaseObserve<DevicesApi.Api>(Api::class.java) {
         observe(api.updateTrafficInfo(trafficReqInfo), null)
     }
 
-    fun uploadGasData(
-        gasList: List<Gas> = emptyList(),
-        callBack: RequestResultCallBack<BaseResponse>
-    ) {
+    suspend fun uploadGasData(
+        gasList: List<Gas> = emptyList()
+    ): BaseResponse {
         val detections = arrayListOf<GasReqBean>()
         gasList.forEach {
             detections.add(GasReqBean(it))
         }
         val gasReq = GasRequest(detections = detections)
-        observe(api.uploadGasData(gasReq), callBack)
+        return api.uploadGasData(gasReq)
     }
 
-    fun getDetectionLastTime(callBack: RequestResultCallBack<LastTimeResponse>) {
-        observe(api.getDetectionLastTime(LztekUtil.getSn()), callBack)
+    suspend fun getDetectionLastTime() : LastTimeResponse{
+        return api.getDetectionLastTime(LztekUtil.getSn())
     }
 
-    fun getVideoLastTime(callBack: RequestResultCallBack<LastTimeResponse>) {
-        observe(api.getVideoLastTime(LztekUtil.getSn()), callBack)
+    suspend fun getVideoLastTime(): LastTimeResponse {
+        return api.getVideoLastTime(LztekUtil.getSn())
     }
 
     interface Api {
@@ -78,14 +77,14 @@ class DevicesApi : BaseObserve<DevicesApi.Api>(Api::class.java) {
 
         @Headers("baseurl:host")
         @POST("/api/device/addDetection")
-        fun uploadGasData(@Body body: GasRequest): Observable<BaseResponse>
+        suspend fun uploadGasData(@Body body: GasRequest): BaseResponse
 
         @Headers("baseurl:host")
         @GET("/api/device/getDetectionLastTime")
-        fun getDetectionLastTime(@Query("deviceSn") sn: String): Observable<LastTimeResponse>
+        suspend fun getDetectionLastTime(@Query("deviceSn") sn: String): LastTimeResponse
 
         @Headers("baseurl:host")
         @GET("/api/device/getVideoLastTime")
-        fun getVideoLastTime(@Query("deviceSn") sn: String): Observable<LastTimeResponse>
+        suspend fun getVideoLastTime(@Query("deviceSn") sn: String): LastTimeResponse
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/net/UploadFileApi.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/net/UploadFileApi.kt
index 878ebb3..d233835 100644
--- a/app/src/main/java/com/yinuo/safetywatcher/watcher/net/UploadFileApi.kt
+++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/net/UploadFileApi.kt
@@ -2,9 +2,7 @@ package com.yinuo.safetywatcher.watcher.net
 
 import com.common.commonlib.net.BaseObserve
 import com.common.commonlib.net.bean.BaseResponse
-import com.common.commonlib.net.callback.RequestResultCallBack
 import com.yinuo.safetywatcher.watcher.utils.LztekUtil
-import io.reactivex.rxjava3.core.Observable
 import okhttp3.MediaType.Companion.toMediaTypeOrNull
 import okhttp3.MultipartBody
 import okhttp3.RequestBody
@@ -24,25 +22,21 @@ const val FORM_DATA = "multipart/form-data";
  */
 class UploadFileApi : BaseObserve<UploadFileApi.Api>(Api::class.java) {
 
-    open fun singleUpload(
+    suspend fun singleUpload(
         path: String,
-        videoTime: Long,
-        callBack: RequestResultCallBack<BaseResponse>
-    ) {
-        observe(
-            api.singleUpload(makeParamsMaps(videoTime), makeFileBodyPart(path)),
-            callBack
-        )
+        videoTime: Long
+    ): BaseResponse {
+        return api.singleUpload(makeParamsMaps(videoTime), makeFileBodyPart(path))
     }
 
     interface Api {
         @Headers("baseurl:host")
         @Multipart
         @POST("/common/uploadVideo")
-        fun singleUpload(
+        suspend fun singleUpload(
             @PartMap params: Map<String, @JvmSuppressWildcards RequestBody>,
             @Part file: MultipartBody.Part
-        ): Observable<BaseResponse>
+        ): BaseResponse
     }
 
     private fun makeFileBodyPart(path: String): MultipartBody.Part {
diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/CloudActivity.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/CloudActivity.kt
index acb02fb..55f3cbf 100644
--- a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/CloudActivity.kt
+++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/CloudActivity.kt
@@ -6,20 +6,18 @@ import android.view.View
 import com.common.commonlib.db.DBUtils
 import com.common.commonlib.db.entity.Gas
 import com.common.commonlib.db.entity.Video
-import com.common.commonlib.net.bean.BaseResponse
-import com.common.commonlib.net.callback.RequestResultCallBack
 import com.yinuo.library.vlc.utils.LogUtils
 import com.yinuo.safetywatcher.R
-import com.yinuo.safetywatcher.TestUtils
 import com.yinuo.safetywatcher.databinding.ActivityCloudBinding
 import com.yinuo.safetywatcher.watcher.base.NoOptionsActivity
-import com.yinuo.safetywatcher.watcher.bean.LastTimeResponse
 import com.yinuo.safetywatcher.watcher.constant.GAS_CLOUD_UPLOAD_SIZE_ONCE
 import com.yinuo.safetywatcher.watcher.net.DevicesApi
 import com.yinuo.safetywatcher.watcher.net.UploadFileApi
+import com.yinuo.safetywatcher.watcher.utils.showToast
 import kotlinx.coroutines.DelicateCoroutinesApi
 import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.launch
+import java.util.concurrent.atomic.AtomicBoolean
 
 class CloudActivity : NoOptionsActivity() {
     private val mBinding: ActivityCloudBinding by lazy {
@@ -34,7 +32,10 @@ class CloudActivity : NoOptionsActivity() {
         DevicesApi()
     }
 
-    override fun getTopBarTitle(): String? {
+    private var uploadingGas = AtomicBoolean(false)
+    private var uploadingVideo = AtomicBoolean(false)
+
+    override fun getTopBarTitle(): String {
         return getString(R.string.cloud)
     }
 
@@ -45,14 +46,32 @@ class CloudActivity : NoOptionsActivity() {
     override fun initView() {
         mBinding.apply {
             syncSensor.setOnClickListener {
+                if (uploadingGas.get()) {
+                    showToast(getString(R.string.repeat_click_sync_tip))
+                    return@setOnClickListener
+                }
                 showLoadingDialog()
-                uploadSensorData()
+                GlobalScope.launch {
+                    uploadSensorData()
+                    closeLoadingDialog()
+                }
             }
             syncVedio.setOnClickListener {
+                if (uploadingVideo.get()) {
+                    showToast(getString(R.string.repeat_click_sync_tip))
+                    return@setOnClickListener
+                }
                 showLoadingDialog()
-                uploadVideo()
+                GlobalScope.launch {
+                    uploadVideo()
+                    closeLoadingDialog()
+                }
             }
             syncOnce.setOnClickListener {
+                if (uploadingGas.get() && uploadingVideo.get()) {
+                    showToast(getString(R.string.repeat_click_sync_tip))
+                    return@setOnClickListener
+                }
                 showLoadingDialog()
                 uploadOnece()
             }
@@ -60,98 +79,92 @@ class CloudActivity : NoOptionsActivity() {
     }
 
     private fun uploadOnece() {
-        uploadSensorData()
-        uploadVideo()
+        GlobalScope.launch {
+            uploadSensorData()
+            uploadVideo()
+            closeLoadingDialog()
+        }
     }
 
-    private fun uploadVideo() {
-        // 1.拿到云端最新数据时间
-        devicesApi.getVideoLastTime(object : RequestResultCallBack<LastTimeResponse>() {
-            override fun onResult(result: LastTimeResponse) {
-                if (result.isOk()) {
-                    val cloudTime = result.data
-                    // 2. 拿到待上传文件列表 上传
-                    getFileListAndUpload(cloudTime)
-                } else {
-                    LogUtils.e("getVideoLastTime error code = ${result.code}")
-                }
-            }
-
-            override fun onError(error: String?) {
-                LogUtils.e(error)
+    private suspend fun uploadVideo() {
+        if (!uploadingVideo.get()) {
+            uploadingVideo.set(true)
+            // 1.拿到云端最新数据时间
+            val timeResponse = devicesApi.getVideoLastTime()
+            if (timeResponse.isOk()) {
+                val cloudTime = timeResponse.data
+                // 2. 拿到待上传文件列表 上传
+                getFileListAndUpload(cloudTime)
+                LogUtils.v("uploadVideo ok")
+            } else {
+                LogUtils.e("getVideoLastTime error code = ${timeResponse.code}")
             }
-        })
+            uploadingVideo.set(false)
+        }
     }
 
-    private fun uploadSensorData() {
-        // 1.拿到云端最新数据时间
-        devicesApi.getVideoLastTime(object : RequestResultCallBack<LastTimeResponse>() {
-            override fun onResult(result: LastTimeResponse) {
-                if (result.isOk()) {
-                    val cloudTime = result.data
-                    // 2. 查询本地数据库中该时间之后的数据
-                    // 3. 上传数据给服务器
-                    getSensorDataUpload(cloudTime)
-                } else {
-                    LogUtils.e("getVideoLastTime error code = ${result.code}")
-                }
-            }
-
-            override fun onError(error: String?) {
-                LogUtils.e(error)
+    private suspend fun uploadSensorData() {
+        if (!uploadingGas.get()) {
+            uploadingGas.set(true)
+            // 1.拿到云端最新数据时间
+            val lastTimeResponse = devicesApi.getDetectionLastTime()
+            if (lastTimeResponse.isOk()) {
+                val cloudTime = lastTimeResponse.data
+                // 2. 查询本地数据库中该时间之后的数据
+                // 3. 上传数据给服务器
+                getSensorDataUpload(cloudTime)
+                LogUtils.v("uploadSensorData ok")
+            } else {
+                LogUtils.e("getVideoLastTime error code = ${lastTimeResponse.code}")
             }
-        })
+            uploadingGas.set(false)
+        }
     }
 
-    private fun getSensorDataUpload(cloudTime: Long) {
-        GlobalScope.launch {
-            val gasList = DBUtils.gasDao().getAllBySyncFlagOrTime(false, cloudTime)
-            val tempList = arrayListOf<Gas>()
-            gasList.forEach {
-                tempList.add(it)
-                if (tempList.size == GAS_CLOUD_UPLOAD_SIZE_ONCE) {
-                    val cloneList: ArrayList<Gas> = tempList.clone() as ArrayList<Gas>
-                    devicesApi.uploadGasData(cloneList, UploadGasCallback(tempList))
-                    tempList.clear()
+    private suspend fun getSensorDataUpload(cloudTime: Long) {
+        val gasList = DBUtils.gasDao().getAllBySyncFlagOrTime(false, cloudTime)
+        val tempList = arrayListOf<Gas>()
+        gasList.forEach {
+            tempList.add(it)
+            if (tempList.size == GAS_CLOUD_UPLOAD_SIZE_ONCE) {
+                val response = devicesApi.uploadGasData(tempList)
+                if (response.isOk()) {
+                    val gasDao = DBUtils.gasDao()
+                    tempList.forEach { gas ->
+                        gas.syncFlag = true
+                        gasDao.update(gas)
+                    }
                 }
-            }
-            if (tempList.isNotEmpty()) {
-                devicesApi.uploadGasData(tempList, UploadGasCallback(tempList))
+                tempList.clear()
             }
         }
-    }
-
-    private fun getFileListAndUpload(cloudTime: Long) {
-        GlobalScope.launch {
-            val videoDao = DBUtils.videoDao()
-            val videoList = videoDao.getAllByTime(cloudTime, System.currentTimeMillis())
-            // 上传
-            videoList.forEach {
-                uploadFile(it)
+        if (tempList.isNotEmpty()) {
+            val response = devicesApi.uploadGasData(tempList)
+            if (response.isOk()) {
+                val gasDao = DBUtils.gasDao()
+                tempList.forEach {
+                    it.syncFlag = true
+                    gasDao.update(it)
+                }
             }
         }
     }
 
-    private fun uploadFile(video: Video) {
-        TestUtils.testUploadFile(uploadApi, video, loadingDialog)
-    }
-
-    class UploadGasCallback(private val upLoadList: ArrayList<Gas>) :
-        RequestResultCallBack<BaseResponse>() {
-        override fun onResult(result: BaseResponse) {
-            GlobalScope.launch {
-                if (result.isOk()) {
-                    val gasDao = DBUtils.gasDao()
-                    upLoadList.forEach {
-                        it.syncFlag = true
-                        gasDao.update(it)
-                    }
-                }
-            }
+    private suspend fun getFileListAndUpload(cloudTime: Long) {
+        val videoDao = DBUtils.videoDao()
+        val videoList = videoDao.getAllByTime(cloudTime, System.currentTimeMillis())
+        // 上传
+        videoList.forEach {
+            uploadFile(it)
         }
+    }
 
-        override fun onError(error: String?) {
-            LogUtils.e("UploadGasCallback $error")
+    private suspend fun uploadFile(video: Video) {
+        val response = uploadApi.singleUpload(video.path, video.time)
+        if (response.isOk()) {
+            val videoDaoImpl = DBUtils.videoDao()
+            video.uploaded = true
+            videoDaoImpl.update(video)
         }
     }
 }
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 25a3ba6..af546ca 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -57,4 +57,5 @@
     <string name="export_data_tip">数据导出中</string>
 
     <string name="connecting_camera">正在连接摄像头...</string>
+    <string name="repeat_click_sync_tip">正在同步中,请勿重复点击</string>
 </resources>
diff --git a/library-common/src/main/java/com/common/commonlib/db/dao/VideoDao.kt b/library-common/src/main/java/com/common/commonlib/db/dao/VideoDao.kt
index bbe47ce..89ad3cd 100644
--- a/library-common/src/main/java/com/common/commonlib/db/dao/VideoDao.kt
+++ b/library-common/src/main/java/com/common/commonlib/db/dao/VideoDao.kt
@@ -4,7 +4,7 @@ import androidx.room.Dao
 import androidx.room.Delete
 import androidx.room.Insert
 import androidx.room.Query
-import com.common.commonlib.db.entity.Gas
+import androidx.room.Update
 import com.common.commonlib.db.entity.Video
 
 @Dao
@@ -23,4 +23,7 @@ interface VideoDao {
 
     @Delete
     suspend fun delete(video: Video)
+
+    @Update
+    suspend fun update(video: Video)
 }
\ No newline at end of file