diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt new file mode 100644 index 0000000..9d7c639 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt @@ -0,0 +1,34 @@ +package com.casic.br.operationsite.test.service + +import android.app.Service +import android.content.Intent +import android.os.IBinder +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.websocket.WebSocketManager + +class WebSocketService : Service() { + + private lateinit var socketManager: WebSocketManager + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + //初始化WebSocket + socketManager = WebSocketManager.Builder() + .setContext(this) + .setRemoteHost("ws://${LocaleConstant.AI_BASE_IP}:8765") + .needReconnect(true) + .setRetryIntervalTime(5000L) + .build() + socketManager.connect() + } + + override fun onDestroy() { + super.onDestroy() + //断开WebSocket + socketManager.close() + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt new file mode 100644 index 0000000..9d7c639 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt @@ -0,0 +1,34 @@ +package com.casic.br.operationsite.test.service + +import android.app.Service +import android.content.Intent +import android.os.IBinder +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.websocket.WebSocketManager + +class WebSocketService : Service() { + + private lateinit var socketManager: WebSocketManager + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + //初始化WebSocket + socketManager = WebSocketManager.Builder() + .setContext(this) + .setRemoteHost("ws://${LocaleConstant.AI_BASE_IP}:8765") + .needReconnect(true) + .setRetryIntervalTime(5000L) + .build() + socketManager.connect() + } + + override fun onDestroy() { + super.onDestroy() + //断开WebSocket + socketManager.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt new file mode 100644 index 0000000..302eb17 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt @@ -0,0 +1,23 @@ +package com.casic.br.operationsite.test.util + +sealed class CurrentScene { + /** + * 交底 + */ + object DISCLOSURE : CurrentScene() + + /** + * 环境检测 + */ + object ENVIRONMENT : CurrentScene() + + /** + * 五必须 + */ + object SUPPLY : CurrentScene() + + /** + * 人员监护 + */ + object GUARDIAN : CurrentScene() +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt new file mode 100644 index 0000000..9d7c639 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt @@ -0,0 +1,34 @@ +package com.casic.br.operationsite.test.service + +import android.app.Service +import android.content.Intent +import android.os.IBinder +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.websocket.WebSocketManager + +class WebSocketService : Service() { + + private lateinit var socketManager: WebSocketManager + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + //初始化WebSocket + socketManager = WebSocketManager.Builder() + .setContext(this) + .setRemoteHost("ws://${LocaleConstant.AI_BASE_IP}:8765") + .needReconnect(true) + .setRetryIntervalTime(5000L) + .build() + socketManager.connect() + } + + override fun onDestroy() { + super.onDestroy() + //断开WebSocket + socketManager.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt new file mode 100644 index 0000000..302eb17 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt @@ -0,0 +1,23 @@ +package com.casic.br.operationsite.test.util + +sealed class CurrentScene { + /** + * 交底 + */ + object DISCLOSURE : CurrentScene() + + /** + * 环境检测 + */ + object ENVIRONMENT : CurrentScene() + + /** + * 五必须 + */ + object SUPPLY : CurrentScene() + + /** + * 人员监护 + */ + object GUARDIAN : CurrentScene() +} diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt index b607548..a6b91e6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt @@ -4,6 +4,5 @@ var projectId = "" var userHelmetCode = "" var uploadFileTaskId = "" - var imageArray = ArrayList>() - var imageId = "" + var currentScene: CurrentScene? = null } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt new file mode 100644 index 0000000..9d7c639 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt @@ -0,0 +1,34 @@ +package com.casic.br.operationsite.test.service + +import android.app.Service +import android.content.Intent +import android.os.IBinder +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.websocket.WebSocketManager + +class WebSocketService : Service() { + + private lateinit var socketManager: WebSocketManager + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + //初始化WebSocket + socketManager = WebSocketManager.Builder() + .setContext(this) + .setRemoteHost("ws://${LocaleConstant.AI_BASE_IP}:8765") + .needReconnect(true) + .setRetryIntervalTime(5000L) + .build() + socketManager.connect() + } + + override fun onDestroy() { + super.onDestroy() + //断开WebSocket + socketManager.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt new file mode 100644 index 0000000..302eb17 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt @@ -0,0 +1,23 @@ +package com.casic.br.operationsite.test.util + +sealed class CurrentScene { + /** + * 交底 + */ + object DISCLOSURE : CurrentScene() + + /** + * 环境检测 + */ + object ENVIRONMENT : CurrentScene() + + /** + * 五必须 + */ + object SUPPLY : CurrentScene() + + /** + * 人员监护 + */ + object GUARDIAN : CurrentScene() +} diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt index b607548..a6b91e6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt @@ -4,6 +4,5 @@ var projectId = "" var userHelmetCode = "" var uploadFileTaskId = "" - var imageArray = ArrayList>() - var imageId = "" + var currentScene: CurrentScene? = null } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt new file mode 100644 index 0000000..03fa6b8 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt @@ -0,0 +1,13 @@ +package com.casic.br.operationsite.test.util.websocket + +import okhttp3.WebSocket + +interface IWebSocketListener { + fun onSocketOpened(webSocket: WebSocket) + + fun onMessageResponse(message: String) + + fun onSocketClosed(code: Int) + + fun onConnectFailed(t: Throwable) +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt new file mode 100644 index 0000000..9d7c639 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt @@ -0,0 +1,34 @@ +package com.casic.br.operationsite.test.service + +import android.app.Service +import android.content.Intent +import android.os.IBinder +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.websocket.WebSocketManager + +class WebSocketService : Service() { + + private lateinit var socketManager: WebSocketManager + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + //初始化WebSocket + socketManager = WebSocketManager.Builder() + .setContext(this) + .setRemoteHost("ws://${LocaleConstant.AI_BASE_IP}:8765") + .needReconnect(true) + .setRetryIntervalTime(5000L) + .build() + socketManager.connect() + } + + override fun onDestroy() { + super.onDestroy() + //断开WebSocket + socketManager.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt new file mode 100644 index 0000000..302eb17 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt @@ -0,0 +1,23 @@ +package com.casic.br.operationsite.test.util + +sealed class CurrentScene { + /** + * 交底 + */ + object DISCLOSURE : CurrentScene() + + /** + * 环境检测 + */ + object ENVIRONMENT : CurrentScene() + + /** + * 五必须 + */ + object SUPPLY : CurrentScene() + + /** + * 人员监护 + */ + object GUARDIAN : CurrentScene() +} diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt index b607548..a6b91e6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt @@ -4,6 +4,5 @@ var projectId = "" var userHelmetCode = "" var uploadFileTaskId = "" - var imageArray = ArrayList>() - var imageId = "" + var currentScene: CurrentScene? = null } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt new file mode 100644 index 0000000..03fa6b8 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt @@ -0,0 +1,13 @@ +package com.casic.br.operationsite.test.util.websocket + +import okhttp3.WebSocket + +interface IWebSocketListener { + fun onSocketOpened(webSocket: WebSocket) + + fun onMessageResponse(message: String) + + fun onSocketClosed(code: Int) + + fun onConnectFailed(t: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt new file mode 100644 index 0000000..3d045a7 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt @@ -0,0 +1,54 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.util.Log +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import okhttp3.WebSocket +import okhttp3.WebSocketListener +import java.util.concurrent.TimeUnit + +class WebSocketClient { + private val kTag = "WebSocketClient" + private lateinit var webSocket: WebSocket + + fun connect(remoteHost: String, listener: IWebSocketListener) { + Log.d(kTag, "connect: $remoteHost") + val request = Request.Builder().url(remoteHost).build() + val httpClient by lazy { + OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build() + } + httpClient.newWebSocket(request, object : WebSocketListener() { + override fun onOpen(webSocket: WebSocket, response: Response) { + super.onOpen(webSocket, response) + this@WebSocketClient.webSocket = webSocket + listener.onSocketOpened(webSocket) + } + + override fun onMessage(webSocket: WebSocket, text: String) { + super.onMessage(webSocket, text) + listener.onMessageResponse(text) + } + + override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { + super.onClosed(webSocket, code, reason) + listener.onSocketClosed(code) + } + + override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { + super.onFailure(webSocket, t, response) + listener.onConnectFailed(t) + } + }) + httpClient.dispatcher.executorService.shutdown() + } + + fun disconnect() { + Log.d(kTag, "disconnect: 断开连接") + webSocket.close(1000, null) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt new file mode 100644 index 0000000..9d7c639 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt @@ -0,0 +1,34 @@ +package com.casic.br.operationsite.test.service + +import android.app.Service +import android.content.Intent +import android.os.IBinder +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.websocket.WebSocketManager + +class WebSocketService : Service() { + + private lateinit var socketManager: WebSocketManager + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + //初始化WebSocket + socketManager = WebSocketManager.Builder() + .setContext(this) + .setRemoteHost("ws://${LocaleConstant.AI_BASE_IP}:8765") + .needReconnect(true) + .setRetryIntervalTime(5000L) + .build() + socketManager.connect() + } + + override fun onDestroy() { + super.onDestroy() + //断开WebSocket + socketManager.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt new file mode 100644 index 0000000..302eb17 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt @@ -0,0 +1,23 @@ +package com.casic.br.operationsite.test.util + +sealed class CurrentScene { + /** + * 交底 + */ + object DISCLOSURE : CurrentScene() + + /** + * 环境检测 + */ + object ENVIRONMENT : CurrentScene() + + /** + * 五必须 + */ + object SUPPLY : CurrentScene() + + /** + * 人员监护 + */ + object GUARDIAN : CurrentScene() +} diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt index b607548..a6b91e6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt @@ -4,6 +4,5 @@ var projectId = "" var userHelmetCode = "" var uploadFileTaskId = "" - var imageArray = ArrayList>() - var imageId = "" + var currentScene: CurrentScene? = null } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt new file mode 100644 index 0000000..03fa6b8 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt @@ -0,0 +1,13 @@ +package com.casic.br.operationsite.test.util.websocket + +import okhttp3.WebSocket + +interface IWebSocketListener { + fun onSocketOpened(webSocket: WebSocket) + + fun onMessageResponse(message: String) + + fun onSocketClosed(code: Int) + + fun onConnectFailed(t: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt new file mode 100644 index 0000000..3d045a7 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt @@ -0,0 +1,54 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.util.Log +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import okhttp3.WebSocket +import okhttp3.WebSocketListener +import java.util.concurrent.TimeUnit + +class WebSocketClient { + private val kTag = "WebSocketClient" + private lateinit var webSocket: WebSocket + + fun connect(remoteHost: String, listener: IWebSocketListener) { + Log.d(kTag, "connect: $remoteHost") + val request = Request.Builder().url(remoteHost).build() + val httpClient by lazy { + OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build() + } + httpClient.newWebSocket(request, object : WebSocketListener() { + override fun onOpen(webSocket: WebSocket, response: Response) { + super.onOpen(webSocket, response) + this@WebSocketClient.webSocket = webSocket + listener.onSocketOpened(webSocket) + } + + override fun onMessage(webSocket: WebSocket, text: String) { + super.onMessage(webSocket, text) + listener.onMessageResponse(text) + } + + override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { + super.onClosed(webSocket, code, reason) + listener.onSocketClosed(code) + } + + override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { + super.onFailure(webSocket, t, response) + listener.onConnectFailed(t) + } + }) + httpClient.dispatcher.executorService.shutdown() + } + + fun disconnect() { + Log.d(kTag, "disconnect: 断开连接") + webSocket.close(1000, null) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt new file mode 100644 index 0000000..a85f94b --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt @@ -0,0 +1,162 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.content.Context +import android.graphics.BitmapFactory +import android.os.Handler +import android.os.Looper +import android.util.Base64 +import com.casic.br.operationsite.test.util.CurrentScene +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache +import com.casic.br.operationsite.test.view.EnvironmentActivity +import com.casic.br.operationsite.test.view.GuardiansActivity +import com.casic.br.operationsite.test.view.SuppliesActivity +import com.pengxh.kt.lite.extensions.createImageFileDir +import com.pengxh.kt.lite.extensions.saveImage +import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import okhttp3.WebSocket +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + + +class WebSocketManager private constructor(builder: Builder) : IWebSocketListener { + + private val kTag = "WebSocketManager" + private val webSocketClient by lazy { WebSocketClient() } + private val retryHandler by lazy { Handler(Looper.getMainLooper()) } + private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } + private val context = builder.context + private val remoteHost = builder.remoteHost + private val need = builder.need + private val retryIntervalTime = builder.retryIntervalTime + private var isConnected = false + + class Builder { + lateinit var context: Context + lateinit var remoteHost: String + var need = true + var retryIntervalTime = 5000L + + fun setContext(context: Context): Builder { + this.context = context + return this + } + + /** + * ws://192.168.10.139:8765 + * */ + fun setRemoteHost(remoteHost: String): Builder { + this.remoteHost = remoteHost + return this + } + + fun needReconnect(need: Boolean): Builder { + this.need = need + return this + } + + fun setRetryIntervalTime(retryIntervalTime: Long): Builder { + this.retryIntervalTime = retryIntervalTime + return this + } + + fun build(): WebSocketManager { + return WebSocketManager(this) + } + } + + /** + * ws://192.168.10.139:8765 + * */ + fun connect() { + synchronized(this) { + CoroutineScope(Dispatchers.IO).launch { + if (!isConnected) { + webSocketClient.connect(remoteHost, this@WebSocketManager) + } else { + close() + } + } + } + } + + private val retryRunnable = Runnable { connect() } + + override fun onSocketOpened(webSocket: WebSocket) { + CoroutineScope(Dispatchers.Main).launch { + "AI连接成功".show(context) + } + } + + override fun onMessageResponse(message: String) { + if (RuntimeCache.currentScene == null) { + return + } + + val base64 = if (RuntimeCache.currentScene == CurrentScene.GUARDIAN) { + message.split(":")[1] + } else { + message + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) + val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) + val imagePath = "/${context.createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" + bitmap.saveImage(imagePath) + + when (RuntimeCache.currentScene) { + CurrentScene.DISCLOSURE -> {} + CurrentScene.ENVIRONMENT -> { + val msg = EnvironmentActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + EnvironmentActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.SUPPLY -> { + val msg = SuppliesActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + SuppliesActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.GUARDIAN -> { + val msg = GuardiansActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + GuardiansActivity.weakReferenceHandler.sendMessage(msg) + } + + else -> { + CoroutineScope(Dispatchers.Main).launch { + "作业阶段错误,请注意流程".show(context) + } + } + } + } + + override fun onSocketClosed(code: Int) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接关闭".show(context) + } + } + + override fun onConnectFailed(t: Throwable) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接失败,正在重连...".show(context) + } + if (need) { + retryHandler.postDelayed(retryRunnable, retryIntervalTime) + } + } + + fun close() { + webSocketClient.disconnect() + retryHandler.removeCallbacks(retryRunnable) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt new file mode 100644 index 0000000..9d7c639 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt @@ -0,0 +1,34 @@ +package com.casic.br.operationsite.test.service + +import android.app.Service +import android.content.Intent +import android.os.IBinder +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.websocket.WebSocketManager + +class WebSocketService : Service() { + + private lateinit var socketManager: WebSocketManager + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + //初始化WebSocket + socketManager = WebSocketManager.Builder() + .setContext(this) + .setRemoteHost("ws://${LocaleConstant.AI_BASE_IP}:8765") + .needReconnect(true) + .setRetryIntervalTime(5000L) + .build() + socketManager.connect() + } + + override fun onDestroy() { + super.onDestroy() + //断开WebSocket + socketManager.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt new file mode 100644 index 0000000..302eb17 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt @@ -0,0 +1,23 @@ +package com.casic.br.operationsite.test.util + +sealed class CurrentScene { + /** + * 交底 + */ + object DISCLOSURE : CurrentScene() + + /** + * 环境检测 + */ + object ENVIRONMENT : CurrentScene() + + /** + * 五必须 + */ + object SUPPLY : CurrentScene() + + /** + * 人员监护 + */ + object GUARDIAN : CurrentScene() +} diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt index b607548..a6b91e6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt @@ -4,6 +4,5 @@ var projectId = "" var userHelmetCode = "" var uploadFileTaskId = "" - var imageArray = ArrayList>() - var imageId = "" + var currentScene: CurrentScene? = null } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt new file mode 100644 index 0000000..03fa6b8 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt @@ -0,0 +1,13 @@ +package com.casic.br.operationsite.test.util.websocket + +import okhttp3.WebSocket + +interface IWebSocketListener { + fun onSocketOpened(webSocket: WebSocket) + + fun onMessageResponse(message: String) + + fun onSocketClosed(code: Int) + + fun onConnectFailed(t: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt new file mode 100644 index 0000000..3d045a7 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt @@ -0,0 +1,54 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.util.Log +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import okhttp3.WebSocket +import okhttp3.WebSocketListener +import java.util.concurrent.TimeUnit + +class WebSocketClient { + private val kTag = "WebSocketClient" + private lateinit var webSocket: WebSocket + + fun connect(remoteHost: String, listener: IWebSocketListener) { + Log.d(kTag, "connect: $remoteHost") + val request = Request.Builder().url(remoteHost).build() + val httpClient by lazy { + OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build() + } + httpClient.newWebSocket(request, object : WebSocketListener() { + override fun onOpen(webSocket: WebSocket, response: Response) { + super.onOpen(webSocket, response) + this@WebSocketClient.webSocket = webSocket + listener.onSocketOpened(webSocket) + } + + override fun onMessage(webSocket: WebSocket, text: String) { + super.onMessage(webSocket, text) + listener.onMessageResponse(text) + } + + override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { + super.onClosed(webSocket, code, reason) + listener.onSocketClosed(code) + } + + override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { + super.onFailure(webSocket, t, response) + listener.onConnectFailed(t) + } + }) + httpClient.dispatcher.executorService.shutdown() + } + + fun disconnect() { + Log.d(kTag, "disconnect: 断开连接") + webSocket.close(1000, null) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt new file mode 100644 index 0000000..a85f94b --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt @@ -0,0 +1,162 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.content.Context +import android.graphics.BitmapFactory +import android.os.Handler +import android.os.Looper +import android.util.Base64 +import com.casic.br.operationsite.test.util.CurrentScene +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache +import com.casic.br.operationsite.test.view.EnvironmentActivity +import com.casic.br.operationsite.test.view.GuardiansActivity +import com.casic.br.operationsite.test.view.SuppliesActivity +import com.pengxh.kt.lite.extensions.createImageFileDir +import com.pengxh.kt.lite.extensions.saveImage +import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import okhttp3.WebSocket +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + + +class WebSocketManager private constructor(builder: Builder) : IWebSocketListener { + + private val kTag = "WebSocketManager" + private val webSocketClient by lazy { WebSocketClient() } + private val retryHandler by lazy { Handler(Looper.getMainLooper()) } + private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } + private val context = builder.context + private val remoteHost = builder.remoteHost + private val need = builder.need + private val retryIntervalTime = builder.retryIntervalTime + private var isConnected = false + + class Builder { + lateinit var context: Context + lateinit var remoteHost: String + var need = true + var retryIntervalTime = 5000L + + fun setContext(context: Context): Builder { + this.context = context + return this + } + + /** + * ws://192.168.10.139:8765 + * */ + fun setRemoteHost(remoteHost: String): Builder { + this.remoteHost = remoteHost + return this + } + + fun needReconnect(need: Boolean): Builder { + this.need = need + return this + } + + fun setRetryIntervalTime(retryIntervalTime: Long): Builder { + this.retryIntervalTime = retryIntervalTime + return this + } + + fun build(): WebSocketManager { + return WebSocketManager(this) + } + } + + /** + * ws://192.168.10.139:8765 + * */ + fun connect() { + synchronized(this) { + CoroutineScope(Dispatchers.IO).launch { + if (!isConnected) { + webSocketClient.connect(remoteHost, this@WebSocketManager) + } else { + close() + } + } + } + } + + private val retryRunnable = Runnable { connect() } + + override fun onSocketOpened(webSocket: WebSocket) { + CoroutineScope(Dispatchers.Main).launch { + "AI连接成功".show(context) + } + } + + override fun onMessageResponse(message: String) { + if (RuntimeCache.currentScene == null) { + return + } + + val base64 = if (RuntimeCache.currentScene == CurrentScene.GUARDIAN) { + message.split(":")[1] + } else { + message + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) + val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) + val imagePath = "/${context.createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" + bitmap.saveImage(imagePath) + + when (RuntimeCache.currentScene) { + CurrentScene.DISCLOSURE -> {} + CurrentScene.ENVIRONMENT -> { + val msg = EnvironmentActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + EnvironmentActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.SUPPLY -> { + val msg = SuppliesActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + SuppliesActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.GUARDIAN -> { + val msg = GuardiansActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + GuardiansActivity.weakReferenceHandler.sendMessage(msg) + } + + else -> { + CoroutineScope(Dispatchers.Main).launch { + "作业阶段错误,请注意流程".show(context) + } + } + } + } + + override fun onSocketClosed(code: Int) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接关闭".show(context) + } + } + + override fun onConnectFailed(t: Throwable) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接失败,正在重连...".show(context) + } + if (need) { + retryHandler.postDelayed(retryRunnable, retryIntervalTime) + } + } + + fun close() { + webSocketClient.disconnect() + retryHandler.removeCallbacks(retryRunnable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt index 57db167..313308e 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt @@ -23,6 +23,8 @@ import com.casic.br.operationsite.test.extensions.combineImagePath import com.casic.br.operationsite.test.extensions.compressImage import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.extensions.upload +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache @@ -144,6 +146,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.DISCLOSURE + cameraExecutor = Executors.newSingleThreadExecutor() cameraProviderFuture = ProcessCameraProvider.getInstance(this) cameraProviderFuture.addListener({ @@ -175,7 +179,7 @@ map["image"] = path map["index"] = index.toString() map["base64"] = "" - RuntimeCache.imageArray.add(map) + map.upload() index++ val url = path.combineImagePath() diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt new file mode 100644 index 0000000..9d7c639 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt @@ -0,0 +1,34 @@ +package com.casic.br.operationsite.test.service + +import android.app.Service +import android.content.Intent +import android.os.IBinder +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.websocket.WebSocketManager + +class WebSocketService : Service() { + + private lateinit var socketManager: WebSocketManager + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + //初始化WebSocket + socketManager = WebSocketManager.Builder() + .setContext(this) + .setRemoteHost("ws://${LocaleConstant.AI_BASE_IP}:8765") + .needReconnect(true) + .setRetryIntervalTime(5000L) + .build() + socketManager.connect() + } + + override fun onDestroy() { + super.onDestroy() + //断开WebSocket + socketManager.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt new file mode 100644 index 0000000..302eb17 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt @@ -0,0 +1,23 @@ +package com.casic.br.operationsite.test.util + +sealed class CurrentScene { + /** + * 交底 + */ + object DISCLOSURE : CurrentScene() + + /** + * 环境检测 + */ + object ENVIRONMENT : CurrentScene() + + /** + * 五必须 + */ + object SUPPLY : CurrentScene() + + /** + * 人员监护 + */ + object GUARDIAN : CurrentScene() +} diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt index b607548..a6b91e6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt @@ -4,6 +4,5 @@ var projectId = "" var userHelmetCode = "" var uploadFileTaskId = "" - var imageArray = ArrayList>() - var imageId = "" + var currentScene: CurrentScene? = null } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt new file mode 100644 index 0000000..03fa6b8 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt @@ -0,0 +1,13 @@ +package com.casic.br.operationsite.test.util.websocket + +import okhttp3.WebSocket + +interface IWebSocketListener { + fun onSocketOpened(webSocket: WebSocket) + + fun onMessageResponse(message: String) + + fun onSocketClosed(code: Int) + + fun onConnectFailed(t: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt new file mode 100644 index 0000000..3d045a7 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt @@ -0,0 +1,54 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.util.Log +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import okhttp3.WebSocket +import okhttp3.WebSocketListener +import java.util.concurrent.TimeUnit + +class WebSocketClient { + private val kTag = "WebSocketClient" + private lateinit var webSocket: WebSocket + + fun connect(remoteHost: String, listener: IWebSocketListener) { + Log.d(kTag, "connect: $remoteHost") + val request = Request.Builder().url(remoteHost).build() + val httpClient by lazy { + OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build() + } + httpClient.newWebSocket(request, object : WebSocketListener() { + override fun onOpen(webSocket: WebSocket, response: Response) { + super.onOpen(webSocket, response) + this@WebSocketClient.webSocket = webSocket + listener.onSocketOpened(webSocket) + } + + override fun onMessage(webSocket: WebSocket, text: String) { + super.onMessage(webSocket, text) + listener.onMessageResponse(text) + } + + override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { + super.onClosed(webSocket, code, reason) + listener.onSocketClosed(code) + } + + override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { + super.onFailure(webSocket, t, response) + listener.onConnectFailed(t) + } + }) + httpClient.dispatcher.executorService.shutdown() + } + + fun disconnect() { + Log.d(kTag, "disconnect: 断开连接") + webSocket.close(1000, null) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt new file mode 100644 index 0000000..a85f94b --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt @@ -0,0 +1,162 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.content.Context +import android.graphics.BitmapFactory +import android.os.Handler +import android.os.Looper +import android.util.Base64 +import com.casic.br.operationsite.test.util.CurrentScene +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache +import com.casic.br.operationsite.test.view.EnvironmentActivity +import com.casic.br.operationsite.test.view.GuardiansActivity +import com.casic.br.operationsite.test.view.SuppliesActivity +import com.pengxh.kt.lite.extensions.createImageFileDir +import com.pengxh.kt.lite.extensions.saveImage +import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import okhttp3.WebSocket +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + + +class WebSocketManager private constructor(builder: Builder) : IWebSocketListener { + + private val kTag = "WebSocketManager" + private val webSocketClient by lazy { WebSocketClient() } + private val retryHandler by lazy { Handler(Looper.getMainLooper()) } + private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } + private val context = builder.context + private val remoteHost = builder.remoteHost + private val need = builder.need + private val retryIntervalTime = builder.retryIntervalTime + private var isConnected = false + + class Builder { + lateinit var context: Context + lateinit var remoteHost: String + var need = true + var retryIntervalTime = 5000L + + fun setContext(context: Context): Builder { + this.context = context + return this + } + + /** + * ws://192.168.10.139:8765 + * */ + fun setRemoteHost(remoteHost: String): Builder { + this.remoteHost = remoteHost + return this + } + + fun needReconnect(need: Boolean): Builder { + this.need = need + return this + } + + fun setRetryIntervalTime(retryIntervalTime: Long): Builder { + this.retryIntervalTime = retryIntervalTime + return this + } + + fun build(): WebSocketManager { + return WebSocketManager(this) + } + } + + /** + * ws://192.168.10.139:8765 + * */ + fun connect() { + synchronized(this) { + CoroutineScope(Dispatchers.IO).launch { + if (!isConnected) { + webSocketClient.connect(remoteHost, this@WebSocketManager) + } else { + close() + } + } + } + } + + private val retryRunnable = Runnable { connect() } + + override fun onSocketOpened(webSocket: WebSocket) { + CoroutineScope(Dispatchers.Main).launch { + "AI连接成功".show(context) + } + } + + override fun onMessageResponse(message: String) { + if (RuntimeCache.currentScene == null) { + return + } + + val base64 = if (RuntimeCache.currentScene == CurrentScene.GUARDIAN) { + message.split(":")[1] + } else { + message + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) + val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) + val imagePath = "/${context.createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" + bitmap.saveImage(imagePath) + + when (RuntimeCache.currentScene) { + CurrentScene.DISCLOSURE -> {} + CurrentScene.ENVIRONMENT -> { + val msg = EnvironmentActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + EnvironmentActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.SUPPLY -> { + val msg = SuppliesActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + SuppliesActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.GUARDIAN -> { + val msg = GuardiansActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + GuardiansActivity.weakReferenceHandler.sendMessage(msg) + } + + else -> { + CoroutineScope(Dispatchers.Main).launch { + "作业阶段错误,请注意流程".show(context) + } + } + } + } + + override fun onSocketClosed(code: Int) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接关闭".show(context) + } + } + + override fun onConnectFailed(t: Throwable) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接失败,正在重连...".show(context) + } + if (need) { + retryHandler.postDelayed(retryRunnable, retryIntervalTime) + } + } + + fun close() { + webSocketClient.disconnect() + retryHandler.removeCallbacks(retryRunnable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt index 57db167..313308e 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt @@ -23,6 +23,8 @@ import com.casic.br.operationsite.test.extensions.combineImagePath import com.casic.br.operationsite.test.extensions.compressImage import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.extensions.upload +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache @@ -144,6 +146,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.DISCLOSURE + cameraExecutor = Executors.newSingleThreadExecutor() cameraProviderFuture = ProcessCameraProvider.getInstance(this) cameraProviderFuture.addListener({ @@ -175,7 +179,7 @@ map["image"] = path map["index"] = index.toString() map["base64"] = "" - RuntimeCache.imageArray.add(map) + map.upload() index++ val url = path.combineImagePath() diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt index 7c8fc4f..91ba0c6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt @@ -1,18 +1,17 @@ package com.casic.br.operationsite.test.view -import android.graphics.BitmapFactory import android.os.Bundle import android.os.Handler import android.os.Message -import android.util.Base64 import android.widget.LinearLayout import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.lifecycleScope import com.casic.br.operationsite.test.R import com.casic.br.operationsite.test.callback.OnImageCompressListener import com.casic.br.operationsite.test.databinding.ActivityEnvironmentBinding import com.casic.br.operationsite.test.extensions.compressImage import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.extensions.upload +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager @@ -22,81 +21,51 @@ import com.casic.br.operationsite.test.vm.WorkSiteViewModel import com.casic.br.operationsite.test.widget.BottomControlSheet import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.createImageFileDir import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.saveImage import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.shuyu.gsyvideoplayer.GSYVideoManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import okhttp3.WebSocket -import okhttp3.WebSocketListener import java.io.File -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale import java.util.Timer import java.util.TimerTask import java.util.UUID -import java.util.concurrent.TimeUnit class EnvironmentActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + lateinit var weakReferenceHandler: WeakReferenceHandler + } + private val kTag = "EnvironmentActivity" private val context = this - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var workSiteViewModel: WorkSiteViewModel private lateinit var timer: Timer - private var webSocket: WebSocket? = null - private var isWebSocketConnected = false private var isConfirmedFirst = false private var isConfirmedSecond = false private var isConfirmedThird = false - private var isDone = false private var imagePath = "" override fun handleMessage(msg: Message): Boolean { - when (msg.what) { - LocaleConstant.WEBSOCKET_CONNECTED_CODE -> "AI连接成功".show(this) + if (msg.what == LocaleConstant.WEBSOCKET_MESSAGE_CODE) { + imagePath = msg.obj as String + //自动上传到服务器 + imagePath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + //上传图片 + uploadFileViewModel.uploadImage(context, file) + } - LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { - try { - val base64 = msg.obj as String - val bitmapArray = Base64.decode(base64, Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) - binding.blowerImageView.setImageBitmap(bitmap) - imagePath = "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" - bitmap.saveImage(imagePath) - - //自动上传到服务器 - imagePath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - //上传图片 - uploadFileViewModel.uploadImage(context, file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) - } catch (e: Exception) { + override fun onError(e: Throwable) { e.printStackTrace() } - } - - LocaleConstant.WEBSOCKET_DISCONNECTED_CODE -> "AI连接失败".show(this) + }) } return true } @@ -164,6 +133,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.ENVIRONMENT + weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] @@ -179,10 +150,7 @@ map["image"] = path map["index"] = "1" map["base64"] = "" - if (!isDone) { - RuntimeCache.imageArray.add(map) - isDone = true - } + map.upload() } } } @@ -234,55 +202,10 @@ timer.schedule(object : TimerTask() { override fun run() { workSiteViewModel.getWorkers(context, RuntimeCache.projectId) - - if (!isWebSocketConnected) { - initWebSocket() - } } }, 0, 2000) } - private fun initWebSocket() { - //初始化WebSocket - val httpClient = OkHttpClient.Builder() - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS) - .writeTimeout(10, TimeUnit.SECONDS) - .build() - lifecycleScope.launch(Dispatchers.IO) { - val request = Request.Builder().url("ws://${LocaleConstant.AI_BASE_IP}:8765").build() - httpClient.newWebSocket(request, object : WebSocketListener() { - override fun onOpen(webSocket: WebSocket, response: Response) { - super.onOpen(webSocket, response) - this@EnvironmentActivity.webSocket = webSocket - isWebSocketConnected = true - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_CONNECTED_CODE) - } - } - - override fun onMessage(webSocket: WebSocket, text: String) { - super.onMessage(webSocket, text) - lifecycleScope.launch(Dispatchers.Main) { - val message = weakReferenceHandler.obtainMessage() - message.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE - message.obj = text - weakReferenceHandler.sendMessage(message) - } - } - - override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - super.onFailure(webSocket, t, response) - isWebSocketConnected = false - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_DISCONNECTED_CODE) - } - } - }) - httpClient.dispatcher.executorService.shutdown() - } - } - override fun initViewBinding(): ActivityEnvironmentBinding { return ActivityEnvironmentBinding.inflate(layoutInflater) } @@ -308,7 +231,6 @@ super.onDestroy() GSYVideoManager.releaseAllVideos() timer.cancel() - webSocket?.close(1000, null) } override fun onPause() { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt new file mode 100644 index 0000000..9d7c639 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt @@ -0,0 +1,34 @@ +package com.casic.br.operationsite.test.service + +import android.app.Service +import android.content.Intent +import android.os.IBinder +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.websocket.WebSocketManager + +class WebSocketService : Service() { + + private lateinit var socketManager: WebSocketManager + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + //初始化WebSocket + socketManager = WebSocketManager.Builder() + .setContext(this) + .setRemoteHost("ws://${LocaleConstant.AI_BASE_IP}:8765") + .needReconnect(true) + .setRetryIntervalTime(5000L) + .build() + socketManager.connect() + } + + override fun onDestroy() { + super.onDestroy() + //断开WebSocket + socketManager.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt new file mode 100644 index 0000000..302eb17 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt @@ -0,0 +1,23 @@ +package com.casic.br.operationsite.test.util + +sealed class CurrentScene { + /** + * 交底 + */ + object DISCLOSURE : CurrentScene() + + /** + * 环境检测 + */ + object ENVIRONMENT : CurrentScene() + + /** + * 五必须 + */ + object SUPPLY : CurrentScene() + + /** + * 人员监护 + */ + object GUARDIAN : CurrentScene() +} diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt index b607548..a6b91e6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt @@ -4,6 +4,5 @@ var projectId = "" var userHelmetCode = "" var uploadFileTaskId = "" - var imageArray = ArrayList>() - var imageId = "" + var currentScene: CurrentScene? = null } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt new file mode 100644 index 0000000..03fa6b8 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt @@ -0,0 +1,13 @@ +package com.casic.br.operationsite.test.util.websocket + +import okhttp3.WebSocket + +interface IWebSocketListener { + fun onSocketOpened(webSocket: WebSocket) + + fun onMessageResponse(message: String) + + fun onSocketClosed(code: Int) + + fun onConnectFailed(t: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt new file mode 100644 index 0000000..3d045a7 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt @@ -0,0 +1,54 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.util.Log +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import okhttp3.WebSocket +import okhttp3.WebSocketListener +import java.util.concurrent.TimeUnit + +class WebSocketClient { + private val kTag = "WebSocketClient" + private lateinit var webSocket: WebSocket + + fun connect(remoteHost: String, listener: IWebSocketListener) { + Log.d(kTag, "connect: $remoteHost") + val request = Request.Builder().url(remoteHost).build() + val httpClient by lazy { + OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build() + } + httpClient.newWebSocket(request, object : WebSocketListener() { + override fun onOpen(webSocket: WebSocket, response: Response) { + super.onOpen(webSocket, response) + this@WebSocketClient.webSocket = webSocket + listener.onSocketOpened(webSocket) + } + + override fun onMessage(webSocket: WebSocket, text: String) { + super.onMessage(webSocket, text) + listener.onMessageResponse(text) + } + + override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { + super.onClosed(webSocket, code, reason) + listener.onSocketClosed(code) + } + + override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { + super.onFailure(webSocket, t, response) + listener.onConnectFailed(t) + } + }) + httpClient.dispatcher.executorService.shutdown() + } + + fun disconnect() { + Log.d(kTag, "disconnect: 断开连接") + webSocket.close(1000, null) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt new file mode 100644 index 0000000..a85f94b --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt @@ -0,0 +1,162 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.content.Context +import android.graphics.BitmapFactory +import android.os.Handler +import android.os.Looper +import android.util.Base64 +import com.casic.br.operationsite.test.util.CurrentScene +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache +import com.casic.br.operationsite.test.view.EnvironmentActivity +import com.casic.br.operationsite.test.view.GuardiansActivity +import com.casic.br.operationsite.test.view.SuppliesActivity +import com.pengxh.kt.lite.extensions.createImageFileDir +import com.pengxh.kt.lite.extensions.saveImage +import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import okhttp3.WebSocket +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + + +class WebSocketManager private constructor(builder: Builder) : IWebSocketListener { + + private val kTag = "WebSocketManager" + private val webSocketClient by lazy { WebSocketClient() } + private val retryHandler by lazy { Handler(Looper.getMainLooper()) } + private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } + private val context = builder.context + private val remoteHost = builder.remoteHost + private val need = builder.need + private val retryIntervalTime = builder.retryIntervalTime + private var isConnected = false + + class Builder { + lateinit var context: Context + lateinit var remoteHost: String + var need = true + var retryIntervalTime = 5000L + + fun setContext(context: Context): Builder { + this.context = context + return this + } + + /** + * ws://192.168.10.139:8765 + * */ + fun setRemoteHost(remoteHost: String): Builder { + this.remoteHost = remoteHost + return this + } + + fun needReconnect(need: Boolean): Builder { + this.need = need + return this + } + + fun setRetryIntervalTime(retryIntervalTime: Long): Builder { + this.retryIntervalTime = retryIntervalTime + return this + } + + fun build(): WebSocketManager { + return WebSocketManager(this) + } + } + + /** + * ws://192.168.10.139:8765 + * */ + fun connect() { + synchronized(this) { + CoroutineScope(Dispatchers.IO).launch { + if (!isConnected) { + webSocketClient.connect(remoteHost, this@WebSocketManager) + } else { + close() + } + } + } + } + + private val retryRunnable = Runnable { connect() } + + override fun onSocketOpened(webSocket: WebSocket) { + CoroutineScope(Dispatchers.Main).launch { + "AI连接成功".show(context) + } + } + + override fun onMessageResponse(message: String) { + if (RuntimeCache.currentScene == null) { + return + } + + val base64 = if (RuntimeCache.currentScene == CurrentScene.GUARDIAN) { + message.split(":")[1] + } else { + message + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) + val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) + val imagePath = "/${context.createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" + bitmap.saveImage(imagePath) + + when (RuntimeCache.currentScene) { + CurrentScene.DISCLOSURE -> {} + CurrentScene.ENVIRONMENT -> { + val msg = EnvironmentActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + EnvironmentActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.SUPPLY -> { + val msg = SuppliesActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + SuppliesActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.GUARDIAN -> { + val msg = GuardiansActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + GuardiansActivity.weakReferenceHandler.sendMessage(msg) + } + + else -> { + CoroutineScope(Dispatchers.Main).launch { + "作业阶段错误,请注意流程".show(context) + } + } + } + } + + override fun onSocketClosed(code: Int) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接关闭".show(context) + } + } + + override fun onConnectFailed(t: Throwable) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接失败,正在重连...".show(context) + } + if (need) { + retryHandler.postDelayed(retryRunnable, retryIntervalTime) + } + } + + fun close() { + webSocketClient.disconnect() + retryHandler.removeCallbacks(retryRunnable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt index 57db167..313308e 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt @@ -23,6 +23,8 @@ import com.casic.br.operationsite.test.extensions.combineImagePath import com.casic.br.operationsite.test.extensions.compressImage import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.extensions.upload +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache @@ -144,6 +146,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.DISCLOSURE + cameraExecutor = Executors.newSingleThreadExecutor() cameraProviderFuture = ProcessCameraProvider.getInstance(this) cameraProviderFuture.addListener({ @@ -175,7 +179,7 @@ map["image"] = path map["index"] = index.toString() map["base64"] = "" - RuntimeCache.imageArray.add(map) + map.upload() index++ val url = path.combineImagePath() diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt index 7c8fc4f..91ba0c6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt @@ -1,18 +1,17 @@ package com.casic.br.operationsite.test.view -import android.graphics.BitmapFactory import android.os.Bundle import android.os.Handler import android.os.Message -import android.util.Base64 import android.widget.LinearLayout import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.lifecycleScope import com.casic.br.operationsite.test.R import com.casic.br.operationsite.test.callback.OnImageCompressListener import com.casic.br.operationsite.test.databinding.ActivityEnvironmentBinding import com.casic.br.operationsite.test.extensions.compressImage import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.extensions.upload +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager @@ -22,81 +21,51 @@ import com.casic.br.operationsite.test.vm.WorkSiteViewModel import com.casic.br.operationsite.test.widget.BottomControlSheet import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.createImageFileDir import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.saveImage import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.shuyu.gsyvideoplayer.GSYVideoManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import okhttp3.WebSocket -import okhttp3.WebSocketListener import java.io.File -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale import java.util.Timer import java.util.TimerTask import java.util.UUID -import java.util.concurrent.TimeUnit class EnvironmentActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + lateinit var weakReferenceHandler: WeakReferenceHandler + } + private val kTag = "EnvironmentActivity" private val context = this - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var workSiteViewModel: WorkSiteViewModel private lateinit var timer: Timer - private var webSocket: WebSocket? = null - private var isWebSocketConnected = false private var isConfirmedFirst = false private var isConfirmedSecond = false private var isConfirmedThird = false - private var isDone = false private var imagePath = "" override fun handleMessage(msg: Message): Boolean { - when (msg.what) { - LocaleConstant.WEBSOCKET_CONNECTED_CODE -> "AI连接成功".show(this) + if (msg.what == LocaleConstant.WEBSOCKET_MESSAGE_CODE) { + imagePath = msg.obj as String + //自动上传到服务器 + imagePath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + //上传图片 + uploadFileViewModel.uploadImage(context, file) + } - LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { - try { - val base64 = msg.obj as String - val bitmapArray = Base64.decode(base64, Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) - binding.blowerImageView.setImageBitmap(bitmap) - imagePath = "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" - bitmap.saveImage(imagePath) - - //自动上传到服务器 - imagePath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - //上传图片 - uploadFileViewModel.uploadImage(context, file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) - } catch (e: Exception) { + override fun onError(e: Throwable) { e.printStackTrace() } - } - - LocaleConstant.WEBSOCKET_DISCONNECTED_CODE -> "AI连接失败".show(this) + }) } return true } @@ -164,6 +133,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.ENVIRONMENT + weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] @@ -179,10 +150,7 @@ map["image"] = path map["index"] = "1" map["base64"] = "" - if (!isDone) { - RuntimeCache.imageArray.add(map) - isDone = true - } + map.upload() } } } @@ -234,55 +202,10 @@ timer.schedule(object : TimerTask() { override fun run() { workSiteViewModel.getWorkers(context, RuntimeCache.projectId) - - if (!isWebSocketConnected) { - initWebSocket() - } } }, 0, 2000) } - private fun initWebSocket() { - //初始化WebSocket - val httpClient = OkHttpClient.Builder() - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS) - .writeTimeout(10, TimeUnit.SECONDS) - .build() - lifecycleScope.launch(Dispatchers.IO) { - val request = Request.Builder().url("ws://${LocaleConstant.AI_BASE_IP}:8765").build() - httpClient.newWebSocket(request, object : WebSocketListener() { - override fun onOpen(webSocket: WebSocket, response: Response) { - super.onOpen(webSocket, response) - this@EnvironmentActivity.webSocket = webSocket - isWebSocketConnected = true - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_CONNECTED_CODE) - } - } - - override fun onMessage(webSocket: WebSocket, text: String) { - super.onMessage(webSocket, text) - lifecycleScope.launch(Dispatchers.Main) { - val message = weakReferenceHandler.obtainMessage() - message.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE - message.obj = text - weakReferenceHandler.sendMessage(message) - } - } - - override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - super.onFailure(webSocket, t, response) - isWebSocketConnected = false - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_DISCONNECTED_CODE) - } - } - }) - httpClient.dispatcher.executorService.shutdown() - } - } - override fun initViewBinding(): ActivityEnvironmentBinding { return ActivityEnvironmentBinding.inflate(layoutInflater) } @@ -308,7 +231,6 @@ super.onDestroy() GSYVideoManager.releaseAllVideos() timer.cancel() - webSocket?.close(1000, null) } override fun onPause() { diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt index 4df106e..3927f29 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt @@ -1,19 +1,17 @@ package com.casic.br.operationsite.test.view -import android.graphics.BitmapFactory import android.os.Bundle import android.os.Handler import android.os.Message import android.text.TextUtils -import android.util.Base64 import android.util.Log import android.view.View import android.widget.FrameLayout import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.lifecycleScope import com.casic.br.operationsite.test.R import com.casic.br.operationsite.test.databinding.ActivityGuardiansBinding import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager @@ -25,11 +23,9 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets -import com.pengxh.kt.lite.extensions.createImageFileDir import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.saveImage import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState @@ -40,35 +36,24 @@ import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.shuyu.gsyvideoplayer.GSYVideoManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import okhttp3.WebSocket -import okhttp3.WebSocketListener -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale import java.util.Timer import java.util.TimerTask -import java.util.concurrent.TimeUnit class GuardiansActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + lateinit var weakReferenceHandler: WeakReferenceHandler + } + private val kTag = "GuardiansActivity" private val context = this - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } private val marginOffset by lazy { 1.dp2px(this) } private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var alarmViewModel: AlarmViewModel private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var workSiteViewModel: WorkSiteViewModel private lateinit var imageAdapter: EditableImageAdapter private lateinit var timer: Timer - private var webSocket: WebSocket? = null - private var isWebSocketConnected = false private var isEndTask = false override fun initEvent() { @@ -201,6 +186,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.GUARDIAN + weakReferenceHandler = WeakReferenceHandler(this) //动态设置rtspPlayerView宽高 @@ -287,10 +274,6 @@ timer.schedule(object : TimerTask() { override fun run() { workSiteViewModel.getWorkers(context, RuntimeCache.projectId) - - if (!isWebSocketConnected) { - initWebSocket() - } } }, 0, 5000) @@ -304,71 +287,18 @@ } override fun handleMessage(msg: Message): Boolean { - when (msg.what) { - LocaleConstant.WEBSOCKET_CONNECTED_CODE -> "AI连接成功".show(this) - - LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { - try { - val base64 = (msg.obj as String).split(":")[1] - val bitmapArray = Base64.decode(base64, Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) - val imagePath = "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" - Log.d(kTag, "imagePath: $imagePath") - bitmap.saveImage(imagePath) - if (recyclerViewImages.size == 3) { - recyclerViewImages.removeFirst() - imageAdapter.notifyDataSetChanged() - } - recyclerViewImages.add(imagePath) - imageAdapter.notifyDataSetChanged() - } catch (e: Exception) { - e.printStackTrace() - } + if (msg.what == LocaleConstant.WEBSOCKET_MESSAGE_CODE) { + val imagePath = msg.obj as String + if (recyclerViewImages.size == 3) { + recyclerViewImages.removeFirst() + imageAdapter.notifyDataSetChanged() } - - LocaleConstant.WEBSOCKET_DISCONNECTED_CODE -> "AI连接失败".show(this) + recyclerViewImages.add(imagePath) + imageAdapter.notifyDataSetChanged() } return true } - private fun initWebSocket() { - //初始化WebSocket - val httpClient = OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).build() - lifecycleScope.launch(Dispatchers.IO) { - val request = Request.Builder().url("ws://${LocaleConstant.AI_BASE_IP}:8765").build() - httpClient.newWebSocket(request, object : WebSocketListener() { - override fun onOpen(webSocket: WebSocket, response: Response) { - super.onOpen(webSocket, response) - this@GuardiansActivity.webSocket = webSocket - isWebSocketConnected = true - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_CONNECTED_CODE) - } - } - - override fun onMessage(webSocket: WebSocket, text: String) { - super.onMessage(webSocket, text) - lifecycleScope.launch(Dispatchers.Main) { - val message = weakReferenceHandler.obtainMessage() - message.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE - message.obj = text - weakReferenceHandler.sendMessage(message) - } - } - - override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - super.onFailure(webSocket, t, response) - isWebSocketConnected = false - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_DISCONNECTED_CODE) - } - } - }) - httpClient.dispatcher.executorService.shutdown() - } - } - override fun initViewBinding(): ActivityGuardiansBinding { return ActivityGuardiansBinding.inflate(layoutInflater) } @@ -412,7 +342,6 @@ AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { isEndTask = true - RuntimeCache.imageArray.clear() constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "stop") } @@ -426,7 +355,6 @@ super.onDestroy() GSYVideoManager.releaseAllVideos() timer.cancel() - webSocket?.close(1000, null) } override fun onPause() { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt new file mode 100644 index 0000000..9d7c639 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt @@ -0,0 +1,34 @@ +package com.casic.br.operationsite.test.service + +import android.app.Service +import android.content.Intent +import android.os.IBinder +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.websocket.WebSocketManager + +class WebSocketService : Service() { + + private lateinit var socketManager: WebSocketManager + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + //初始化WebSocket + socketManager = WebSocketManager.Builder() + .setContext(this) + .setRemoteHost("ws://${LocaleConstant.AI_BASE_IP}:8765") + .needReconnect(true) + .setRetryIntervalTime(5000L) + .build() + socketManager.connect() + } + + override fun onDestroy() { + super.onDestroy() + //断开WebSocket + socketManager.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt new file mode 100644 index 0000000..302eb17 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt @@ -0,0 +1,23 @@ +package com.casic.br.operationsite.test.util + +sealed class CurrentScene { + /** + * 交底 + */ + object DISCLOSURE : CurrentScene() + + /** + * 环境检测 + */ + object ENVIRONMENT : CurrentScene() + + /** + * 五必须 + */ + object SUPPLY : CurrentScene() + + /** + * 人员监护 + */ + object GUARDIAN : CurrentScene() +} diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt index b607548..a6b91e6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt @@ -4,6 +4,5 @@ var projectId = "" var userHelmetCode = "" var uploadFileTaskId = "" - var imageArray = ArrayList>() - var imageId = "" + var currentScene: CurrentScene? = null } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt new file mode 100644 index 0000000..03fa6b8 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt @@ -0,0 +1,13 @@ +package com.casic.br.operationsite.test.util.websocket + +import okhttp3.WebSocket + +interface IWebSocketListener { + fun onSocketOpened(webSocket: WebSocket) + + fun onMessageResponse(message: String) + + fun onSocketClosed(code: Int) + + fun onConnectFailed(t: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt new file mode 100644 index 0000000..3d045a7 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt @@ -0,0 +1,54 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.util.Log +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import okhttp3.WebSocket +import okhttp3.WebSocketListener +import java.util.concurrent.TimeUnit + +class WebSocketClient { + private val kTag = "WebSocketClient" + private lateinit var webSocket: WebSocket + + fun connect(remoteHost: String, listener: IWebSocketListener) { + Log.d(kTag, "connect: $remoteHost") + val request = Request.Builder().url(remoteHost).build() + val httpClient by lazy { + OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build() + } + httpClient.newWebSocket(request, object : WebSocketListener() { + override fun onOpen(webSocket: WebSocket, response: Response) { + super.onOpen(webSocket, response) + this@WebSocketClient.webSocket = webSocket + listener.onSocketOpened(webSocket) + } + + override fun onMessage(webSocket: WebSocket, text: String) { + super.onMessage(webSocket, text) + listener.onMessageResponse(text) + } + + override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { + super.onClosed(webSocket, code, reason) + listener.onSocketClosed(code) + } + + override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { + super.onFailure(webSocket, t, response) + listener.onConnectFailed(t) + } + }) + httpClient.dispatcher.executorService.shutdown() + } + + fun disconnect() { + Log.d(kTag, "disconnect: 断开连接") + webSocket.close(1000, null) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt new file mode 100644 index 0000000..a85f94b --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt @@ -0,0 +1,162 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.content.Context +import android.graphics.BitmapFactory +import android.os.Handler +import android.os.Looper +import android.util.Base64 +import com.casic.br.operationsite.test.util.CurrentScene +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache +import com.casic.br.operationsite.test.view.EnvironmentActivity +import com.casic.br.operationsite.test.view.GuardiansActivity +import com.casic.br.operationsite.test.view.SuppliesActivity +import com.pengxh.kt.lite.extensions.createImageFileDir +import com.pengxh.kt.lite.extensions.saveImage +import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import okhttp3.WebSocket +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + + +class WebSocketManager private constructor(builder: Builder) : IWebSocketListener { + + private val kTag = "WebSocketManager" + private val webSocketClient by lazy { WebSocketClient() } + private val retryHandler by lazy { Handler(Looper.getMainLooper()) } + private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } + private val context = builder.context + private val remoteHost = builder.remoteHost + private val need = builder.need + private val retryIntervalTime = builder.retryIntervalTime + private var isConnected = false + + class Builder { + lateinit var context: Context + lateinit var remoteHost: String + var need = true + var retryIntervalTime = 5000L + + fun setContext(context: Context): Builder { + this.context = context + return this + } + + /** + * ws://192.168.10.139:8765 + * */ + fun setRemoteHost(remoteHost: String): Builder { + this.remoteHost = remoteHost + return this + } + + fun needReconnect(need: Boolean): Builder { + this.need = need + return this + } + + fun setRetryIntervalTime(retryIntervalTime: Long): Builder { + this.retryIntervalTime = retryIntervalTime + return this + } + + fun build(): WebSocketManager { + return WebSocketManager(this) + } + } + + /** + * ws://192.168.10.139:8765 + * */ + fun connect() { + synchronized(this) { + CoroutineScope(Dispatchers.IO).launch { + if (!isConnected) { + webSocketClient.connect(remoteHost, this@WebSocketManager) + } else { + close() + } + } + } + } + + private val retryRunnable = Runnable { connect() } + + override fun onSocketOpened(webSocket: WebSocket) { + CoroutineScope(Dispatchers.Main).launch { + "AI连接成功".show(context) + } + } + + override fun onMessageResponse(message: String) { + if (RuntimeCache.currentScene == null) { + return + } + + val base64 = if (RuntimeCache.currentScene == CurrentScene.GUARDIAN) { + message.split(":")[1] + } else { + message + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) + val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) + val imagePath = "/${context.createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" + bitmap.saveImage(imagePath) + + when (RuntimeCache.currentScene) { + CurrentScene.DISCLOSURE -> {} + CurrentScene.ENVIRONMENT -> { + val msg = EnvironmentActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + EnvironmentActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.SUPPLY -> { + val msg = SuppliesActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + SuppliesActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.GUARDIAN -> { + val msg = GuardiansActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + GuardiansActivity.weakReferenceHandler.sendMessage(msg) + } + + else -> { + CoroutineScope(Dispatchers.Main).launch { + "作业阶段错误,请注意流程".show(context) + } + } + } + } + + override fun onSocketClosed(code: Int) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接关闭".show(context) + } + } + + override fun onConnectFailed(t: Throwable) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接失败,正在重连...".show(context) + } + if (need) { + retryHandler.postDelayed(retryRunnable, retryIntervalTime) + } + } + + fun close() { + webSocketClient.disconnect() + retryHandler.removeCallbacks(retryRunnable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt index 57db167..313308e 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt @@ -23,6 +23,8 @@ import com.casic.br.operationsite.test.extensions.combineImagePath import com.casic.br.operationsite.test.extensions.compressImage import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.extensions.upload +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache @@ -144,6 +146,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.DISCLOSURE + cameraExecutor = Executors.newSingleThreadExecutor() cameraProviderFuture = ProcessCameraProvider.getInstance(this) cameraProviderFuture.addListener({ @@ -175,7 +179,7 @@ map["image"] = path map["index"] = index.toString() map["base64"] = "" - RuntimeCache.imageArray.add(map) + map.upload() index++ val url = path.combineImagePath() diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt index 7c8fc4f..91ba0c6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt @@ -1,18 +1,17 @@ package com.casic.br.operationsite.test.view -import android.graphics.BitmapFactory import android.os.Bundle import android.os.Handler import android.os.Message -import android.util.Base64 import android.widget.LinearLayout import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.lifecycleScope import com.casic.br.operationsite.test.R import com.casic.br.operationsite.test.callback.OnImageCompressListener import com.casic.br.operationsite.test.databinding.ActivityEnvironmentBinding import com.casic.br.operationsite.test.extensions.compressImage import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.extensions.upload +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager @@ -22,81 +21,51 @@ import com.casic.br.operationsite.test.vm.WorkSiteViewModel import com.casic.br.operationsite.test.widget.BottomControlSheet import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.createImageFileDir import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.saveImage import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.shuyu.gsyvideoplayer.GSYVideoManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import okhttp3.WebSocket -import okhttp3.WebSocketListener import java.io.File -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale import java.util.Timer import java.util.TimerTask import java.util.UUID -import java.util.concurrent.TimeUnit class EnvironmentActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + lateinit var weakReferenceHandler: WeakReferenceHandler + } + private val kTag = "EnvironmentActivity" private val context = this - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var workSiteViewModel: WorkSiteViewModel private lateinit var timer: Timer - private var webSocket: WebSocket? = null - private var isWebSocketConnected = false private var isConfirmedFirst = false private var isConfirmedSecond = false private var isConfirmedThird = false - private var isDone = false private var imagePath = "" override fun handleMessage(msg: Message): Boolean { - when (msg.what) { - LocaleConstant.WEBSOCKET_CONNECTED_CODE -> "AI连接成功".show(this) + if (msg.what == LocaleConstant.WEBSOCKET_MESSAGE_CODE) { + imagePath = msg.obj as String + //自动上传到服务器 + imagePath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + //上传图片 + uploadFileViewModel.uploadImage(context, file) + } - LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { - try { - val base64 = msg.obj as String - val bitmapArray = Base64.decode(base64, Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) - binding.blowerImageView.setImageBitmap(bitmap) - imagePath = "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" - bitmap.saveImage(imagePath) - - //自动上传到服务器 - imagePath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - //上传图片 - uploadFileViewModel.uploadImage(context, file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) - } catch (e: Exception) { + override fun onError(e: Throwable) { e.printStackTrace() } - } - - LocaleConstant.WEBSOCKET_DISCONNECTED_CODE -> "AI连接失败".show(this) + }) } return true } @@ -164,6 +133,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.ENVIRONMENT + weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] @@ -179,10 +150,7 @@ map["image"] = path map["index"] = "1" map["base64"] = "" - if (!isDone) { - RuntimeCache.imageArray.add(map) - isDone = true - } + map.upload() } } } @@ -234,55 +202,10 @@ timer.schedule(object : TimerTask() { override fun run() { workSiteViewModel.getWorkers(context, RuntimeCache.projectId) - - if (!isWebSocketConnected) { - initWebSocket() - } } }, 0, 2000) } - private fun initWebSocket() { - //初始化WebSocket - val httpClient = OkHttpClient.Builder() - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS) - .writeTimeout(10, TimeUnit.SECONDS) - .build() - lifecycleScope.launch(Dispatchers.IO) { - val request = Request.Builder().url("ws://${LocaleConstant.AI_BASE_IP}:8765").build() - httpClient.newWebSocket(request, object : WebSocketListener() { - override fun onOpen(webSocket: WebSocket, response: Response) { - super.onOpen(webSocket, response) - this@EnvironmentActivity.webSocket = webSocket - isWebSocketConnected = true - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_CONNECTED_CODE) - } - } - - override fun onMessage(webSocket: WebSocket, text: String) { - super.onMessage(webSocket, text) - lifecycleScope.launch(Dispatchers.Main) { - val message = weakReferenceHandler.obtainMessage() - message.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE - message.obj = text - weakReferenceHandler.sendMessage(message) - } - } - - override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - super.onFailure(webSocket, t, response) - isWebSocketConnected = false - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_DISCONNECTED_CODE) - } - } - }) - httpClient.dispatcher.executorService.shutdown() - } - } - override fun initViewBinding(): ActivityEnvironmentBinding { return ActivityEnvironmentBinding.inflate(layoutInflater) } @@ -308,7 +231,6 @@ super.onDestroy() GSYVideoManager.releaseAllVideos() timer.cancel() - webSocket?.close(1000, null) } override fun onPause() { diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt index 4df106e..3927f29 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt @@ -1,19 +1,17 @@ package com.casic.br.operationsite.test.view -import android.graphics.BitmapFactory import android.os.Bundle import android.os.Handler import android.os.Message import android.text.TextUtils -import android.util.Base64 import android.util.Log import android.view.View import android.widget.FrameLayout import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.lifecycleScope import com.casic.br.operationsite.test.R import com.casic.br.operationsite.test.databinding.ActivityGuardiansBinding import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager @@ -25,11 +23,9 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets -import com.pengxh.kt.lite.extensions.createImageFileDir import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.saveImage import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState @@ -40,35 +36,24 @@ import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.shuyu.gsyvideoplayer.GSYVideoManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import okhttp3.WebSocket -import okhttp3.WebSocketListener -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale import java.util.Timer import java.util.TimerTask -import java.util.concurrent.TimeUnit class GuardiansActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + lateinit var weakReferenceHandler: WeakReferenceHandler + } + private val kTag = "GuardiansActivity" private val context = this - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } private val marginOffset by lazy { 1.dp2px(this) } private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var alarmViewModel: AlarmViewModel private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var workSiteViewModel: WorkSiteViewModel private lateinit var imageAdapter: EditableImageAdapter private lateinit var timer: Timer - private var webSocket: WebSocket? = null - private var isWebSocketConnected = false private var isEndTask = false override fun initEvent() { @@ -201,6 +186,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.GUARDIAN + weakReferenceHandler = WeakReferenceHandler(this) //动态设置rtspPlayerView宽高 @@ -287,10 +274,6 @@ timer.schedule(object : TimerTask() { override fun run() { workSiteViewModel.getWorkers(context, RuntimeCache.projectId) - - if (!isWebSocketConnected) { - initWebSocket() - } } }, 0, 5000) @@ -304,71 +287,18 @@ } override fun handleMessage(msg: Message): Boolean { - when (msg.what) { - LocaleConstant.WEBSOCKET_CONNECTED_CODE -> "AI连接成功".show(this) - - LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { - try { - val base64 = (msg.obj as String).split(":")[1] - val bitmapArray = Base64.decode(base64, Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) - val imagePath = "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" - Log.d(kTag, "imagePath: $imagePath") - bitmap.saveImage(imagePath) - if (recyclerViewImages.size == 3) { - recyclerViewImages.removeFirst() - imageAdapter.notifyDataSetChanged() - } - recyclerViewImages.add(imagePath) - imageAdapter.notifyDataSetChanged() - } catch (e: Exception) { - e.printStackTrace() - } + if (msg.what == LocaleConstant.WEBSOCKET_MESSAGE_CODE) { + val imagePath = msg.obj as String + if (recyclerViewImages.size == 3) { + recyclerViewImages.removeFirst() + imageAdapter.notifyDataSetChanged() } - - LocaleConstant.WEBSOCKET_DISCONNECTED_CODE -> "AI连接失败".show(this) + recyclerViewImages.add(imagePath) + imageAdapter.notifyDataSetChanged() } return true } - private fun initWebSocket() { - //初始化WebSocket - val httpClient = OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).build() - lifecycleScope.launch(Dispatchers.IO) { - val request = Request.Builder().url("ws://${LocaleConstant.AI_BASE_IP}:8765").build() - httpClient.newWebSocket(request, object : WebSocketListener() { - override fun onOpen(webSocket: WebSocket, response: Response) { - super.onOpen(webSocket, response) - this@GuardiansActivity.webSocket = webSocket - isWebSocketConnected = true - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_CONNECTED_CODE) - } - } - - override fun onMessage(webSocket: WebSocket, text: String) { - super.onMessage(webSocket, text) - lifecycleScope.launch(Dispatchers.Main) { - val message = weakReferenceHandler.obtainMessage() - message.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE - message.obj = text - weakReferenceHandler.sendMessage(message) - } - } - - override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - super.onFailure(webSocket, t, response) - isWebSocketConnected = false - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_DISCONNECTED_CODE) - } - } - }) - httpClient.dispatcher.executorService.shutdown() - } - } - override fun initViewBinding(): ActivityGuardiansBinding { return ActivityGuardiansBinding.inflate(layoutInflater) } @@ -412,7 +342,6 @@ AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { isEndTask = true - RuntimeCache.imageArray.clear() constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "stop") } @@ -426,7 +355,6 @@ super.onDestroy() GSYVideoManager.releaseAllVideos() timer.cancel() - webSocket?.close(1000, null) } override fun onPause() { diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/SuppliesActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/SuppliesActivity.kt index fcdfe88..0445500 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/SuppliesActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/SuppliesActivity.kt @@ -1,10 +1,8 @@ package com.casic.br.operationsite.test.view -import android.graphics.BitmapFactory import android.os.Bundle import android.os.Handler import android.os.Message -import android.util.Base64 import android.view.View import android.widget.LinearLayout import androidx.lifecycle.ViewModelProvider @@ -14,6 +12,8 @@ import com.casic.br.operationsite.test.databinding.ActivitySuppliesBinding import com.casic.br.operationsite.test.extensions.compressImage import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.extensions.upload +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager @@ -24,11 +24,9 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets -import com.pengxh.kt.lite.extensions.createImageFileDir import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.saveImage import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.WeakReferenceHandler @@ -39,34 +37,22 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import okhttp3.WebSocket -import okhttp3.WebSocketListener import java.io.File -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale -import java.util.Timer -import java.util.TimerTask import java.util.UUID -import java.util.concurrent.TimeUnit class SuppliesActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + lateinit var weakReferenceHandler: WeakReferenceHandler + } + private val kTag = "SuppliesActivity" private val context = this - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } private val marginOffset by lazy { 1.dp2px(this) } private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var imageAdapter: EditableImageAdapter - private lateinit var timer: Timer - private var webSocket: WebSocket? = null - private var isWebSocketConnected = false private var index = 1 private var clickTimes = 1 private var isUnderHandleImage = false @@ -90,19 +76,6 @@ recyclerViewImages.clear() imageAdapter.notifyDataSetChanged() - //将属于此阶段的数据暂时缓存起来 - val temp = ArrayList>() - RuntimeCache.imageArray.forEach { - if (it.values.contains("before_operation_protection")) { - temp.add(it) - } - } - - //将缓存的数据从源数据中分别剔除 - temp.forEach { - RuntimeCache.imageArray.remove(it) - } - //本地角标重置 index = 1 @@ -172,47 +145,11 @@ } } - private fun initWebSocket() { - //初始化WebSocket - val httpClient = OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).build() - lifecycleScope.launch(Dispatchers.IO) { - val request = Request.Builder().url("ws://${LocaleConstant.AI_BASE_IP}:8765").build() - httpClient.newWebSocket(request, object : WebSocketListener() { - override fun onOpen(webSocket: WebSocket, response: Response) { - super.onOpen(webSocket, response) - this@SuppliesActivity.webSocket = webSocket - isWebSocketConnected = true - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_CONNECTED_CODE) - } - } - - override fun onMessage(webSocket: WebSocket, text: String) { - super.onMessage(webSocket, text) - lifecycleScope.launch(Dispatchers.Main) { - val message = weakReferenceHandler.obtainMessage() - message.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE - message.obj = text - weakReferenceHandler.sendMessage(message) - } - } - - override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - super.onFailure(webSocket, t, response) - isWebSocketConnected = false - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_DISCONNECTED_CODE) - } - } - }) - httpClient.dispatcher.executorService.shutdown() - } - } - override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.SUPPLY + weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] @@ -228,7 +165,7 @@ map["image"] = path map["index"] = index.toString() map["base64"] = "" - RuntimeCache.imageArray.add(map) + map.upload() index++ isUnderHandleImage = false } @@ -246,15 +183,6 @@ binding.rtspPlayerView, LocaleConstant.SUB_RTSP_URL ) - timer = Timer() - timer.schedule(object : TimerTask() { - override fun run() { - if (!isWebSocketConnected) { - initWebSocket() - } - } - }, 0, 2000) - //左右边距 imageAdapter = EditableImageAdapter(this, recyclerViewImages, videoWidth, 5, 3) binding.recyclerView.addItemDecoration( @@ -264,63 +192,49 @@ } override fun handleMessage(msg: Message): Boolean { - when (msg.what) { - LocaleConstant.WEBSOCKET_CONNECTED_CODE -> "AI连接成功".show(this) + if (msg.what == LocaleConstant.WEBSOCKET_MESSAGE_CODE) { + if (!isUnderHandleImage) { + isUnderHandleImage = true - LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { - try { - if (!isUnderHandleImage) { - isUnderHandleImage = true - val base64 = msg.obj as String - val bitmapArray = Base64.decode(base64, Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) - val imagePath = - "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" - bitmap.saveImage(imagePath) - recyclerViewImages.add(imagePath) - imageAdapter.notifyDataSetChanged() + val imagePath = msg.obj as String + recyclerViewImages.add(imagePath) + imageAdapter.notifyDataSetChanged() - //自动上传到服务器 - imagePath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - //上传图片 - uploadFileViewModel.uploadImage(context, file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) - - when (recyclerViewImages.size) { - 1 -> binding.stepView.text = "稍后开始检查第二项:安全帽,请准备" - 2 -> binding.stepView.text = "稍后开始检查第三项:灭火器,请准备" - 3 -> binding.stepView.text = "稍后开始检查第四项:鼓风机,请准备" - 4 -> binding.stepView.text = "稍后开始检查第五项:警示牌,请准备" - 5 -> AlertControlDialog.Builder() - .setContext(this) - .setTitle("温馨提示") - .setMessage("检测到施工前劳保用品准备完毕,是否开始施工?") - .setNegativeButton("取消").setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { -// SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) - navigatePageTo() - } - - override fun onCancelClick() { - - } - }).build().show() - } + //自动上传到服务器 + imagePath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + //上传图片 + uploadFileViewModel.uploadImage(context, file) } - } catch (e: Exception) { - e.printStackTrace() + + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + + when (recyclerViewImages.size) { + 1 -> binding.stepView.text = "稍后开始检查第二项:安全帽,请准备" + 2 -> binding.stepView.text = "稍后开始检查第三项:灭火器,请准备" + 3 -> binding.stepView.text = "稍后开始检查第四项:鼓风机,请准备" + 4 -> binding.stepView.text = "稍后开始检查第五项:警示牌,请准备" + 5 -> AlertControlDialog.Builder() + .setContext(this) + .setTitle("温馨提示") + .setMessage("检测到施工前劳保用品准备完毕,是否开始施工?") + .setNegativeButton("取消").setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { +// SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) + navigatePageTo() + } + + override fun onCancelClick() { + + } + }).build().show() } } - - LocaleConstant.WEBSOCKET_DISCONNECTED_CODE -> "AI连接失败".show(this) } return true } @@ -349,8 +263,6 @@ override fun onDestroy() { super.onDestroy() GSYVideoManager.releaseAllVideos() - timer.cancel() - webSocket?.close(1000, null) } override fun onPause() { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a86e57..d0b021a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt new file mode 100644 index 0000000..73162bc --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/extensions/HashMap.kt @@ -0,0 +1,21 @@ +package com.casic.br.operationsite.test.extensions + +import com.casic.br.operationsite.test.util.AuthenticationHelper +import com.casic.br.operationsite.test.util.HttpRequestHelper +import com.casic.br.operationsite.test.util.LocaleConstant + +fun HashMap.upload() { + HttpRequestHelper.Builder() + .setAuthentication("token", AuthenticationHelper.token!!) + .setRequestParam(this) + .setRequestTarget(LocaleConstant.IMAGE_BED_URL) + .setOnHttpRequestCallback(object : HttpRequestHelper.OnHttpRequestCallback { + override fun onSuccess(result: String) { + + } + + override fun onFailure(throwable: Throwable) { + + } + }).build().start() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt deleted file mode 100644 index e7b9477..0000000 --- a/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.casic.br.operationsite.test.service - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import android.util.Log -import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.util.AuthenticationHelper -import com.casic.br.operationsite.test.util.HttpRequestHelper -import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache -import java.util.Timer -import java.util.TimerTask - -class UploadImageService : Service() { - - private val kTag = "UploadImageService" - private var isUploading = false - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onCreate() { - super.onCreate() - Timer().schedule(object : TimerTask() { - override fun run() { - if (!isUploading) { - if (RuntimeCache.imageArray.isNotEmpty()) { - isUploading = true - val map = RuntimeCache.imageArray.first() - if (RuntimeCache.imageId != map["imageId"]) { - RuntimeCache.imageId = map["imageId"].toString() - HttpRequestHelper.Builder() - .setAuthentication("token", AuthenticationHelper.token!!) - .setRequestParam(map) - .setRequestTarget(LocaleConstant.IMAGE_BED_URL) - .setOnHttpRequestCallback(object : - HttpRequestHelper.OnHttpRequestCallback { - override fun onSuccess(result: String) { - isUploading = false - if (result.getResponseCode() == 200) { - RuntimeCache.imageArray.removeFirst() - RuntimeCache.imageId = "" - } - } - - override fun onFailure(throwable: Throwable) { - isUploading = false - } - }).build().start() - } else { - Log.d(kTag, "run: 重复上传") - } - } else { - Log.d(kTag, "run: 图片队列为空") - } - } else { - Log.d(kTag, "run: 当前图片暂未上传成功") - } - } - }, 0, 5000) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - return START_STICKY - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt new file mode 100644 index 0000000..9d7c639 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/WebSocketService.kt @@ -0,0 +1,34 @@ +package com.casic.br.operationsite.test.service + +import android.app.Service +import android.content.Intent +import android.os.IBinder +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.websocket.WebSocketManager + +class WebSocketService : Service() { + + private lateinit var socketManager: WebSocketManager + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onCreate() { + super.onCreate() + //初始化WebSocket + socketManager = WebSocketManager.Builder() + .setContext(this) + .setRemoteHost("ws://${LocaleConstant.AI_BASE_IP}:8765") + .needReconnect(true) + .setRetryIntervalTime(5000L) + .build() + socketManager.connect() + } + + override fun onDestroy() { + super.onDestroy() + //断开WebSocket + socketManager.close() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt new file mode 100644 index 0000000..302eb17 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/CurrentScene.kt @@ -0,0 +1,23 @@ +package com.casic.br.operationsite.test.util + +sealed class CurrentScene { + /** + * 交底 + */ + object DISCLOSURE : CurrentScene() + + /** + * 环境检测 + */ + object ENVIRONMENT : CurrentScene() + + /** + * 五必须 + */ + object SUPPLY : CurrentScene() + + /** + * 人员监护 + */ + object GUARDIAN : CurrentScene() +} diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt index b607548..a6b91e6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/RuntimeCache.kt @@ -4,6 +4,5 @@ var projectId = "" var userHelmetCode = "" var uploadFileTaskId = "" - var imageArray = ArrayList>() - var imageId = "" + var currentScene: CurrentScene? = null } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt new file mode 100644 index 0000000..03fa6b8 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/IWebSocketListener.kt @@ -0,0 +1,13 @@ +package com.casic.br.operationsite.test.util.websocket + +import okhttp3.WebSocket + +interface IWebSocketListener { + fun onSocketOpened(webSocket: WebSocket) + + fun onMessageResponse(message: String) + + fun onSocketClosed(code: Int) + + fun onConnectFailed(t: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt new file mode 100644 index 0000000..3d045a7 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketClient.kt @@ -0,0 +1,54 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.util.Log +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import okhttp3.WebSocket +import okhttp3.WebSocketListener +import java.util.concurrent.TimeUnit + +class WebSocketClient { + private val kTag = "WebSocketClient" + private lateinit var webSocket: WebSocket + + fun connect(remoteHost: String, listener: IWebSocketListener) { + Log.d(kTag, "connect: $remoteHost") + val request = Request.Builder().url(remoteHost).build() + val httpClient by lazy { + OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build() + } + httpClient.newWebSocket(request, object : WebSocketListener() { + override fun onOpen(webSocket: WebSocket, response: Response) { + super.onOpen(webSocket, response) + this@WebSocketClient.webSocket = webSocket + listener.onSocketOpened(webSocket) + } + + override fun onMessage(webSocket: WebSocket, text: String) { + super.onMessage(webSocket, text) + listener.onMessageResponse(text) + } + + override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { + super.onClosed(webSocket, code, reason) + listener.onSocketClosed(code) + } + + override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { + super.onFailure(webSocket, t, response) + listener.onConnectFailed(t) + } + }) + httpClient.dispatcher.executorService.shutdown() + } + + fun disconnect() { + Log.d(kTag, "disconnect: 断开连接") + webSocket.close(1000, null) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt new file mode 100644 index 0000000..a85f94b --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/websocket/WebSocketManager.kt @@ -0,0 +1,162 @@ +package com.casic.br.operationsite.test.util.websocket + +import android.content.Context +import android.graphics.BitmapFactory +import android.os.Handler +import android.os.Looper +import android.util.Base64 +import com.casic.br.operationsite.test.util.CurrentScene +import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache +import com.casic.br.operationsite.test.view.EnvironmentActivity +import com.casic.br.operationsite.test.view.GuardiansActivity +import com.casic.br.operationsite.test.view.SuppliesActivity +import com.pengxh.kt.lite.extensions.createImageFileDir +import com.pengxh.kt.lite.extensions.saveImage +import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import okhttp3.WebSocket +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + + +class WebSocketManager private constructor(builder: Builder) : IWebSocketListener { + + private val kTag = "WebSocketManager" + private val webSocketClient by lazy { WebSocketClient() } + private val retryHandler by lazy { Handler(Looper.getMainLooper()) } + private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } + private val context = builder.context + private val remoteHost = builder.remoteHost + private val need = builder.need + private val retryIntervalTime = builder.retryIntervalTime + private var isConnected = false + + class Builder { + lateinit var context: Context + lateinit var remoteHost: String + var need = true + var retryIntervalTime = 5000L + + fun setContext(context: Context): Builder { + this.context = context + return this + } + + /** + * ws://192.168.10.139:8765 + * */ + fun setRemoteHost(remoteHost: String): Builder { + this.remoteHost = remoteHost + return this + } + + fun needReconnect(need: Boolean): Builder { + this.need = need + return this + } + + fun setRetryIntervalTime(retryIntervalTime: Long): Builder { + this.retryIntervalTime = retryIntervalTime + return this + } + + fun build(): WebSocketManager { + return WebSocketManager(this) + } + } + + /** + * ws://192.168.10.139:8765 + * */ + fun connect() { + synchronized(this) { + CoroutineScope(Dispatchers.IO).launch { + if (!isConnected) { + webSocketClient.connect(remoteHost, this@WebSocketManager) + } else { + close() + } + } + } + } + + private val retryRunnable = Runnable { connect() } + + override fun onSocketOpened(webSocket: WebSocket) { + CoroutineScope(Dispatchers.Main).launch { + "AI连接成功".show(context) + } + } + + override fun onMessageResponse(message: String) { + if (RuntimeCache.currentScene == null) { + return + } + + val base64 = if (RuntimeCache.currentScene == CurrentScene.GUARDIAN) { + message.split(":")[1] + } else { + message + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) + val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) + val imagePath = "/${context.createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" + bitmap.saveImage(imagePath) + + when (RuntimeCache.currentScene) { + CurrentScene.DISCLOSURE -> {} + CurrentScene.ENVIRONMENT -> { + val msg = EnvironmentActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + EnvironmentActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.SUPPLY -> { + val msg = SuppliesActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + SuppliesActivity.weakReferenceHandler.sendMessage(msg) + } + + CurrentScene.GUARDIAN -> { + val msg = GuardiansActivity.weakReferenceHandler.obtainMessage() + msg.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE + msg.obj = imagePath + GuardiansActivity.weakReferenceHandler.sendMessage(msg) + } + + else -> { + CoroutineScope(Dispatchers.Main).launch { + "作业阶段错误,请注意流程".show(context) + } + } + } + } + + override fun onSocketClosed(code: Int) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接关闭".show(context) + } + } + + override fun onConnectFailed(t: Throwable) { + isConnected = false + CoroutineScope(Dispatchers.Main).launch { + "AI连接失败,正在重连...".show(context) + } + if (need) { + retryHandler.postDelayed(retryRunnable, retryIntervalTime) + } + } + + fun close() { + webSocketClient.disconnect() + retryHandler.removeCallbacks(retryRunnable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt index 57db167..313308e 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/DisclosureActivity.kt @@ -23,6 +23,8 @@ import com.casic.br.operationsite.test.extensions.combineImagePath import com.casic.br.operationsite.test.extensions.compressImage import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.extensions.upload +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache @@ -144,6 +146,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.DISCLOSURE + cameraExecutor = Executors.newSingleThreadExecutor() cameraProviderFuture = ProcessCameraProvider.getInstance(this) cameraProviderFuture.addListener({ @@ -175,7 +179,7 @@ map["image"] = path map["index"] = index.toString() map["base64"] = "" - RuntimeCache.imageArray.add(map) + map.upload() index++ val url = path.combineImagePath() diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt index 7c8fc4f..91ba0c6 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/EnvironmentActivity.kt @@ -1,18 +1,17 @@ package com.casic.br.operationsite.test.view -import android.graphics.BitmapFactory import android.os.Bundle import android.os.Handler import android.os.Message -import android.util.Base64 import android.widget.LinearLayout import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.lifecycleScope import com.casic.br.operationsite.test.R import com.casic.br.operationsite.test.callback.OnImageCompressListener import com.casic.br.operationsite.test.databinding.ActivityEnvironmentBinding import com.casic.br.operationsite.test.extensions.compressImage import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.extensions.upload +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager @@ -22,81 +21,51 @@ import com.casic.br.operationsite.test.vm.WorkSiteViewModel import com.casic.br.operationsite.test.widget.BottomControlSheet import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.createImageFileDir import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.saveImage import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView import com.shuyu.gsyvideoplayer.GSYVideoManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import okhttp3.WebSocket -import okhttp3.WebSocketListener import java.io.File -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale import java.util.Timer import java.util.TimerTask import java.util.UUID -import java.util.concurrent.TimeUnit class EnvironmentActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + lateinit var weakReferenceHandler: WeakReferenceHandler + } + private val kTag = "EnvironmentActivity" private val context = this - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var workSiteViewModel: WorkSiteViewModel private lateinit var timer: Timer - private var webSocket: WebSocket? = null - private var isWebSocketConnected = false private var isConfirmedFirst = false private var isConfirmedSecond = false private var isConfirmedThird = false - private var isDone = false private var imagePath = "" override fun handleMessage(msg: Message): Boolean { - when (msg.what) { - LocaleConstant.WEBSOCKET_CONNECTED_CODE -> "AI连接成功".show(this) + if (msg.what == LocaleConstant.WEBSOCKET_MESSAGE_CODE) { + imagePath = msg.obj as String + //自动上传到服务器 + imagePath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + //上传图片 + uploadFileViewModel.uploadImage(context, file) + } - LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { - try { - val base64 = msg.obj as String - val bitmapArray = Base64.decode(base64, Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) - binding.blowerImageView.setImageBitmap(bitmap) - imagePath = "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" - bitmap.saveImage(imagePath) - - //自动上传到服务器 - imagePath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - //上传图片 - uploadFileViewModel.uploadImage(context, file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) - } catch (e: Exception) { + override fun onError(e: Throwable) { e.printStackTrace() } - } - - LocaleConstant.WEBSOCKET_DISCONNECTED_CODE -> "AI连接失败".show(this) + }) } return true } @@ -164,6 +133,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.ENVIRONMENT + weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] @@ -179,10 +150,7 @@ map["image"] = path map["index"] = "1" map["base64"] = "" - if (!isDone) { - RuntimeCache.imageArray.add(map) - isDone = true - } + map.upload() } } } @@ -234,55 +202,10 @@ timer.schedule(object : TimerTask() { override fun run() { workSiteViewModel.getWorkers(context, RuntimeCache.projectId) - - if (!isWebSocketConnected) { - initWebSocket() - } } }, 0, 2000) } - private fun initWebSocket() { - //初始化WebSocket - val httpClient = OkHttpClient.Builder() - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS) - .writeTimeout(10, TimeUnit.SECONDS) - .build() - lifecycleScope.launch(Dispatchers.IO) { - val request = Request.Builder().url("ws://${LocaleConstant.AI_BASE_IP}:8765").build() - httpClient.newWebSocket(request, object : WebSocketListener() { - override fun onOpen(webSocket: WebSocket, response: Response) { - super.onOpen(webSocket, response) - this@EnvironmentActivity.webSocket = webSocket - isWebSocketConnected = true - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_CONNECTED_CODE) - } - } - - override fun onMessage(webSocket: WebSocket, text: String) { - super.onMessage(webSocket, text) - lifecycleScope.launch(Dispatchers.Main) { - val message = weakReferenceHandler.obtainMessage() - message.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE - message.obj = text - weakReferenceHandler.sendMessage(message) - } - } - - override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - super.onFailure(webSocket, t, response) - isWebSocketConnected = false - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_DISCONNECTED_CODE) - } - } - }) - httpClient.dispatcher.executorService.shutdown() - } - } - override fun initViewBinding(): ActivityEnvironmentBinding { return ActivityEnvironmentBinding.inflate(layoutInflater) } @@ -308,7 +231,6 @@ super.onDestroy() GSYVideoManager.releaseAllVideos() timer.cancel() - webSocket?.close(1000, null) } override fun onPause() { diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt index 4df106e..3927f29 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/GuardiansActivity.kt @@ -1,19 +1,17 @@ package com.casic.br.operationsite.test.view -import android.graphics.BitmapFactory import android.os.Bundle import android.os.Handler import android.os.Message import android.text.TextUtils -import android.util.Base64 import android.util.Log import android.view.View import android.widget.FrameLayout import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.lifecycleScope import com.casic.br.operationsite.test.R import com.casic.br.operationsite.test.databinding.ActivityGuardiansBinding import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager @@ -25,11 +23,9 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets -import com.pengxh.kt.lite.extensions.createImageFileDir import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.saveImage import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.LoadState @@ -40,35 +36,24 @@ import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.shuyu.gsyvideoplayer.GSYVideoManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import okhttp3.WebSocket -import okhttp3.WebSocketListener -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale import java.util.Timer import java.util.TimerTask -import java.util.concurrent.TimeUnit class GuardiansActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + lateinit var weakReferenceHandler: WeakReferenceHandler + } + private val kTag = "GuardiansActivity" private val context = this - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } private val marginOffset by lazy { 1.dp2px(this) } private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var alarmViewModel: AlarmViewModel private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var workSiteViewModel: WorkSiteViewModel private lateinit var imageAdapter: EditableImageAdapter private lateinit var timer: Timer - private var webSocket: WebSocket? = null - private var isWebSocketConnected = false private var isEndTask = false override fun initEvent() { @@ -201,6 +186,8 @@ override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.GUARDIAN + weakReferenceHandler = WeakReferenceHandler(this) //动态设置rtspPlayerView宽高 @@ -287,10 +274,6 @@ timer.schedule(object : TimerTask() { override fun run() { workSiteViewModel.getWorkers(context, RuntimeCache.projectId) - - if (!isWebSocketConnected) { - initWebSocket() - } } }, 0, 5000) @@ -304,71 +287,18 @@ } override fun handleMessage(msg: Message): Boolean { - when (msg.what) { - LocaleConstant.WEBSOCKET_CONNECTED_CODE -> "AI连接成功".show(this) - - LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { - try { - val base64 = (msg.obj as String).split(":")[1] - val bitmapArray = Base64.decode(base64, Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) - val imagePath = "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" - Log.d(kTag, "imagePath: $imagePath") - bitmap.saveImage(imagePath) - if (recyclerViewImages.size == 3) { - recyclerViewImages.removeFirst() - imageAdapter.notifyDataSetChanged() - } - recyclerViewImages.add(imagePath) - imageAdapter.notifyDataSetChanged() - } catch (e: Exception) { - e.printStackTrace() - } + if (msg.what == LocaleConstant.WEBSOCKET_MESSAGE_CODE) { + val imagePath = msg.obj as String + if (recyclerViewImages.size == 3) { + recyclerViewImages.removeFirst() + imageAdapter.notifyDataSetChanged() } - - LocaleConstant.WEBSOCKET_DISCONNECTED_CODE -> "AI连接失败".show(this) + recyclerViewImages.add(imagePath) + imageAdapter.notifyDataSetChanged() } return true } - private fun initWebSocket() { - //初始化WebSocket - val httpClient = OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).build() - lifecycleScope.launch(Dispatchers.IO) { - val request = Request.Builder().url("ws://${LocaleConstant.AI_BASE_IP}:8765").build() - httpClient.newWebSocket(request, object : WebSocketListener() { - override fun onOpen(webSocket: WebSocket, response: Response) { - super.onOpen(webSocket, response) - this@GuardiansActivity.webSocket = webSocket - isWebSocketConnected = true - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_CONNECTED_CODE) - } - } - - override fun onMessage(webSocket: WebSocket, text: String) { - super.onMessage(webSocket, text) - lifecycleScope.launch(Dispatchers.Main) { - val message = weakReferenceHandler.obtainMessage() - message.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE - message.obj = text - weakReferenceHandler.sendMessage(message) - } - } - - override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - super.onFailure(webSocket, t, response) - isWebSocketConnected = false - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_DISCONNECTED_CODE) - } - } - }) - httpClient.dispatcher.executorService.shutdown() - } - } - override fun initViewBinding(): ActivityGuardiansBinding { return ActivityGuardiansBinding.inflate(layoutInflater) } @@ -412,7 +342,6 @@ AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { isEndTask = true - RuntimeCache.imageArray.clear() constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "stop") } @@ -426,7 +355,6 @@ super.onDestroy() GSYVideoManager.releaseAllVideos() timer.cancel() - webSocket?.close(1000, null) } override fun onPause() { diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/SuppliesActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/SuppliesActivity.kt index fcdfe88..0445500 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/SuppliesActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/SuppliesActivity.kt @@ -1,10 +1,8 @@ package com.casic.br.operationsite.test.view -import android.graphics.BitmapFactory import android.os.Bundle import android.os.Handler import android.os.Message -import android.util.Base64 import android.view.View import android.widget.LinearLayout import androidx.lifecycle.ViewModelProvider @@ -14,6 +12,8 @@ import com.casic.br.operationsite.test.databinding.ActivitySuppliesBinding import com.casic.br.operationsite.test.extensions.compressImage import com.casic.br.operationsite.test.extensions.initImmersionBar +import com.casic.br.operationsite.test.extensions.upload +import com.casic.br.operationsite.test.util.CurrentScene import com.casic.br.operationsite.test.util.LocaleConstant import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager @@ -24,11 +24,9 @@ import com.pengxh.kt.lite.adapter.EditableImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.divider.RecyclerViewItemOffsets -import com.pengxh.kt.lite.extensions.createImageFileDir import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo -import com.pengxh.kt.lite.extensions.saveImage import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.ActivityStackManager import com.pengxh.kt.lite.utils.WeakReferenceHandler @@ -39,34 +37,22 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import okhttp3.WebSocket -import okhttp3.WebSocketListener import java.io.File -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale -import java.util.Timer -import java.util.TimerTask import java.util.UUID -import java.util.concurrent.TimeUnit class SuppliesActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + lateinit var weakReferenceHandler: WeakReferenceHandler + } + private val kTag = "SuppliesActivity" private val context = this - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } private val marginOffset by lazy { 1.dp2px(this) } private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 - private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var imageAdapter: EditableImageAdapter - private lateinit var timer: Timer - private var webSocket: WebSocket? = null - private var isWebSocketConnected = false private var index = 1 private var clickTimes = 1 private var isUnderHandleImage = false @@ -90,19 +76,6 @@ recyclerViewImages.clear() imageAdapter.notifyDataSetChanged() - //将属于此阶段的数据暂时缓存起来 - val temp = ArrayList>() - RuntimeCache.imageArray.forEach { - if (it.values.contains("before_operation_protection")) { - temp.add(it) - } - } - - //将缓存的数据从源数据中分别剔除 - temp.forEach { - RuntimeCache.imageArray.remove(it) - } - //本地角标重置 index = 1 @@ -172,47 +145,11 @@ } } - private fun initWebSocket() { - //初始化WebSocket - val httpClient = OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).build() - lifecycleScope.launch(Dispatchers.IO) { - val request = Request.Builder().url("ws://${LocaleConstant.AI_BASE_IP}:8765").build() - httpClient.newWebSocket(request, object : WebSocketListener() { - override fun onOpen(webSocket: WebSocket, response: Response) { - super.onOpen(webSocket, response) - this@SuppliesActivity.webSocket = webSocket - isWebSocketConnected = true - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_CONNECTED_CODE) - } - } - - override fun onMessage(webSocket: WebSocket, text: String) { - super.onMessage(webSocket, text) - lifecycleScope.launch(Dispatchers.Main) { - val message = weakReferenceHandler.obtainMessage() - message.what = LocaleConstant.WEBSOCKET_MESSAGE_CODE - message.obj = text - weakReferenceHandler.sendMessage(message) - } - } - - override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - super.onFailure(webSocket, t, response) - isWebSocketConnected = false - lifecycleScope.launch(Dispatchers.Main) { - weakReferenceHandler.sendEmptyMessage(LocaleConstant.WEBSOCKET_DISCONNECTED_CODE) - } - } - }) - httpClient.dispatcher.executorService.shutdown() - } - } - override fun initOnCreate(savedInstanceState: Bundle?) { ActivityStackManager.addActivity(this) + RuntimeCache.currentScene = CurrentScene.SUPPLY + weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] @@ -228,7 +165,7 @@ map["image"] = path map["index"] = index.toString() map["base64"] = "" - RuntimeCache.imageArray.add(map) + map.upload() index++ isUnderHandleImage = false } @@ -246,15 +183,6 @@ binding.rtspPlayerView, LocaleConstant.SUB_RTSP_URL ) - timer = Timer() - timer.schedule(object : TimerTask() { - override fun run() { - if (!isWebSocketConnected) { - initWebSocket() - } - } - }, 0, 2000) - //左右边距 imageAdapter = EditableImageAdapter(this, recyclerViewImages, videoWidth, 5, 3) binding.recyclerView.addItemDecoration( @@ -264,63 +192,49 @@ } override fun handleMessage(msg: Message): Boolean { - when (msg.what) { - LocaleConstant.WEBSOCKET_CONNECTED_CODE -> "AI连接成功".show(this) + if (msg.what == LocaleConstant.WEBSOCKET_MESSAGE_CODE) { + if (!isUnderHandleImage) { + isUnderHandleImage = true - LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { - try { - if (!isUnderHandleImage) { - isUnderHandleImage = true - val base64 = msg.obj as String - val bitmapArray = Base64.decode(base64, Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) - val imagePath = - "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" - bitmap.saveImage(imagePath) - recyclerViewImages.add(imagePath) - imageAdapter.notifyDataSetChanged() + val imagePath = msg.obj as String + recyclerViewImages.add(imagePath) + imageAdapter.notifyDataSetChanged() - //自动上传到服务器 - imagePath.compressImage(this, object : OnImageCompressListener { - override fun onSuccess(file: File) { - //上传图片 - uploadFileViewModel.uploadImage(context, file) - } - - override fun onError(e: Throwable) { - e.printStackTrace() - } - }) - - when (recyclerViewImages.size) { - 1 -> binding.stepView.text = "稍后开始检查第二项:安全帽,请准备" - 2 -> binding.stepView.text = "稍后开始检查第三项:灭火器,请准备" - 3 -> binding.stepView.text = "稍后开始检查第四项:鼓风机,请准备" - 4 -> binding.stepView.text = "稍后开始检查第五项:警示牌,请准备" - 5 -> AlertControlDialog.Builder() - .setContext(this) - .setTitle("温馨提示") - .setMessage("检测到施工前劳保用品准备完毕,是否开始施工?") - .setNegativeButton("取消").setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { -// SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) - navigatePageTo() - } - - override fun onCancelClick() { - - } - }).build().show() - } + //自动上传到服务器 + imagePath.compressImage(this, object : OnImageCompressListener { + override fun onSuccess(file: File) { + //上传图片 + uploadFileViewModel.uploadImage(context, file) } - } catch (e: Exception) { - e.printStackTrace() + + override fun onError(e: Throwable) { + e.printStackTrace() + } + }) + + when (recyclerViewImages.size) { + 1 -> binding.stepView.text = "稍后开始检查第二项:安全帽,请准备" + 2 -> binding.stepView.text = "稍后开始检查第三项:灭火器,请准备" + 3 -> binding.stepView.text = "稍后开始检查第四项:鼓风机,请准备" + 4 -> binding.stepView.text = "稍后开始检查第五项:警示牌,请准备" + 5 -> AlertControlDialog.Builder() + .setContext(this) + .setTitle("温馨提示") + .setMessage("检测到施工前劳保用品准备完毕,是否开始施工?") + .setNegativeButton("取消").setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { +// SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) + navigatePageTo() + } + + override fun onCancelClick() { + + } + }).build().show() } } - - LocaleConstant.WEBSOCKET_DISCONNECTED_CODE -> "AI连接失败".show(this) } return true } @@ -349,8 +263,6 @@ override fun onDestroy() { super.onDestroy() GSYVideoManager.releaseAllVideos() - timer.cancel() - webSocket?.close(1000, null) } override fun onPause() { diff --git a/app/src/main/java/com/casic/br/operationsite/test/view/WorkTaskActivity.kt b/app/src/main/java/com/casic/br/operationsite/test/view/WorkTaskActivity.kt index 0721c79..aa577b1 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/view/WorkTaskActivity.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/view/WorkTaskActivity.kt @@ -12,7 +12,7 @@ import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.model.WorkSiteListModel import com.casic.br.operationsite.test.service.TcpMessageService -import com.casic.br.operationsite.test.service.UploadImageService +import com.casic.br.operationsite.test.service.WebSocketService import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.vm.LoginViewModel @@ -65,7 +65,7 @@ weakReferenceHandler = WeakReferenceHandler(this) startService(Intent(this, TcpMessageService::class.java)) - startService(Intent(this, UploadImageService::class.java)) + startService(Intent(this, WebSocketService::class.java)) workSiteViewModel = ViewModelProvider(this)[WorkSiteViewModel::class.java] getProjectListByPage()