diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { 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 new file mode 100644 index 0000000..e7b9477 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt @@ -0,0 +1,68 @@ +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 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { 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 new file mode 100644 index 0000000..e7b9477 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt @@ -0,0 +1,68 @@ +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/util/HttpRequestHelper.kt b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt new file mode 100644 index 0000000..e522224 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt @@ -0,0 +1,132 @@ +package com.casic.br.operationsite.test.util + +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.lifecycleScope +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.pengxh.kt.lite.utils.Constant +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.logging.HttpLoggingInterceptor +import java.io.IOException +import java.util.concurrent.TimeUnit + +/** + * Service里面的Http请求 + * */ +class HttpRequestHelper(builder: Builder) : LifecycleOwner { + + private val kTag = "HttpRequestHelper" + private val registry = LifecycleRegistry(this) + private val gson by lazy { Gson() } + + class Builder { + lateinit var key: String + lateinit var value: String + lateinit var map: HashMap + lateinit var url: String + lateinit var httpRequestCallback: OnHttpRequestCallback + + /** + * 设置网络请求鉴权 + */ + fun setAuthentication(key: String = "token", value: String = ""): Builder { + this.key = key + this.value = value + return this + } + + /** + * 设置网络请求参数 + * */ + fun setRequestParam(map: HashMap): Builder { + this.map = map + return this + } + + /** + * 设置网络请求接口地址 + * */ + fun setRequestTarget(url: String): Builder { + this.url = url + return this + } + + /** + * 设置网络请求回调监听 + * */ + fun setOnHttpRequestCallback(httpRequestCallback: OnHttpRequestCallback): Builder { + this.httpRequestCallback = httpRequestCallback + return this + } + + fun build(): HttpRequestHelper { + return HttpRequestHelper(this) + } + } + + private val key = builder.key + private val value = builder.value + private val map = builder.map + private val url = builder.url + private val callback = builder.httpRequestCallback + + /** + * 发起网络请求 + * */ + fun start() { + val param = JsonObject() + map.forEach { + param.add(it.key, gson.toJsonTree(it.value)) + } + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + //构建Request + val request = Request.Builder().addHeader(key, value).post(requestBody).url(url).build() + lifecycleScope.launch(Dispatchers.IO) { + val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(interceptor) + .readTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .build() + try { + val response = client.newCall(request).execute() + response.body?.apply { + withContext(Dispatchers.Main) { + callback.onSuccess(string()) + } + } + } catch (e: IOException) { + withContext(Dispatchers.Main) { + callback.onFailure(e) + } + } + } + } + + interface OnHttpRequestCallback { + fun onSuccess(result: String) + + fun onFailure(throwable: Throwable) + } + + override fun getLifecycle(): Lifecycle { + return registry + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { 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 new file mode 100644 index 0000000..e7b9477 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt @@ -0,0 +1,68 @@ +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/util/HttpRequestHelper.kt b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt new file mode 100644 index 0000000..e522224 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt @@ -0,0 +1,132 @@ +package com.casic.br.operationsite.test.util + +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.lifecycleScope +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.pengxh.kt.lite.utils.Constant +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.logging.HttpLoggingInterceptor +import java.io.IOException +import java.util.concurrent.TimeUnit + +/** + * Service里面的Http请求 + * */ +class HttpRequestHelper(builder: Builder) : LifecycleOwner { + + private val kTag = "HttpRequestHelper" + private val registry = LifecycleRegistry(this) + private val gson by lazy { Gson() } + + class Builder { + lateinit var key: String + lateinit var value: String + lateinit var map: HashMap + lateinit var url: String + lateinit var httpRequestCallback: OnHttpRequestCallback + + /** + * 设置网络请求鉴权 + */ + fun setAuthentication(key: String = "token", value: String = ""): Builder { + this.key = key + this.value = value + return this + } + + /** + * 设置网络请求参数 + * */ + fun setRequestParam(map: HashMap): Builder { + this.map = map + return this + } + + /** + * 设置网络请求接口地址 + * */ + fun setRequestTarget(url: String): Builder { + this.url = url + return this + } + + /** + * 设置网络请求回调监听 + * */ + fun setOnHttpRequestCallback(httpRequestCallback: OnHttpRequestCallback): Builder { + this.httpRequestCallback = httpRequestCallback + return this + } + + fun build(): HttpRequestHelper { + return HttpRequestHelper(this) + } + } + + private val key = builder.key + private val value = builder.value + private val map = builder.map + private val url = builder.url + private val callback = builder.httpRequestCallback + + /** + * 发起网络请求 + * */ + fun start() { + val param = JsonObject() + map.forEach { + param.add(it.key, gson.toJsonTree(it.value)) + } + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + //构建Request + val request = Request.Builder().addHeader(key, value).post(requestBody).url(url).build() + lifecycleScope.launch(Dispatchers.IO) { + val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(interceptor) + .readTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .build() + try { + val response = client.newCall(request).execute() + response.body?.apply { + withContext(Dispatchers.Main) { + callback.onSuccess(string()) + } + } + } catch (e: IOException) { + withContext(Dispatchers.Main) { + callback.onFailure(e) + } + } + } + } + + interface OnHttpRequestCallback { + fun onSuccess(result: String) + + fun onFailure(throwable: Throwable) + } + + override fun getLifecycle(): Lifecycle { + return registry + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt index ba40569..34e438c 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt @@ -29,21 +29,22 @@ } const val SERVER_BASE_URL = "http://111.198.10.15:22006" + const val IMAGE_BED_URL = "${SERVER_BASE_URL}/emergency/prepareUpload" //一体机DeviceMonitor程序TCP Server IP地址 const val GAS_BASE_IP = "192.168.10.139" //一体机算法程序IP地址 - const val AI_BASE_IP = "192.168.10.139" + const val AI_BASE_IP = GAS_BASE_IP //相机IP const val CAMERA_IP = "192.168.10.137" //主码流 - const val MAIN_RTSP_URL = "rtsp://192.168.10.137:554" + const val MAIN_RTSP_URL = "rtsp://${CAMERA_IP}:554" //子码流 - const val SUB_RTSP_URL = "rtsp://192.168.10.137:554/h265/ch1/sub/av_stream" + const val SUB_RTSP_URL = "${MAIN_RTSP_URL}/h265/ch1/sub/av_stream" const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" const val DEVICE_CONTROL_SERVER_CONFIG = "deviceControlServerConfig" const val ACCOUNT = "account" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { 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 new file mode 100644 index 0000000..e7b9477 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt @@ -0,0 +1,68 @@ +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/util/HttpRequestHelper.kt b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt new file mode 100644 index 0000000..e522224 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt @@ -0,0 +1,132 @@ +package com.casic.br.operationsite.test.util + +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.lifecycleScope +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.pengxh.kt.lite.utils.Constant +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.logging.HttpLoggingInterceptor +import java.io.IOException +import java.util.concurrent.TimeUnit + +/** + * Service里面的Http请求 + * */ +class HttpRequestHelper(builder: Builder) : LifecycleOwner { + + private val kTag = "HttpRequestHelper" + private val registry = LifecycleRegistry(this) + private val gson by lazy { Gson() } + + class Builder { + lateinit var key: String + lateinit var value: String + lateinit var map: HashMap + lateinit var url: String + lateinit var httpRequestCallback: OnHttpRequestCallback + + /** + * 设置网络请求鉴权 + */ + fun setAuthentication(key: String = "token", value: String = ""): Builder { + this.key = key + this.value = value + return this + } + + /** + * 设置网络请求参数 + * */ + fun setRequestParam(map: HashMap): Builder { + this.map = map + return this + } + + /** + * 设置网络请求接口地址 + * */ + fun setRequestTarget(url: String): Builder { + this.url = url + return this + } + + /** + * 设置网络请求回调监听 + * */ + fun setOnHttpRequestCallback(httpRequestCallback: OnHttpRequestCallback): Builder { + this.httpRequestCallback = httpRequestCallback + return this + } + + fun build(): HttpRequestHelper { + return HttpRequestHelper(this) + } + } + + private val key = builder.key + private val value = builder.value + private val map = builder.map + private val url = builder.url + private val callback = builder.httpRequestCallback + + /** + * 发起网络请求 + * */ + fun start() { + val param = JsonObject() + map.forEach { + param.add(it.key, gson.toJsonTree(it.value)) + } + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + //构建Request + val request = Request.Builder().addHeader(key, value).post(requestBody).url(url).build() + lifecycleScope.launch(Dispatchers.IO) { + val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(interceptor) + .readTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .build() + try { + val response = client.newCall(request).execute() + response.body?.apply { + withContext(Dispatchers.Main) { + callback.onSuccess(string()) + } + } + } catch (e: IOException) { + withContext(Dispatchers.Main) { + callback.onFailure(e) + } + } + } + } + + interface OnHttpRequestCallback { + fun onSuccess(result: String) + + fun onFailure(throwable: Throwable) + } + + override fun getLifecycle(): Lifecycle { + return registry + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt index ba40569..34e438c 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt @@ -29,21 +29,22 @@ } const val SERVER_BASE_URL = "http://111.198.10.15:22006" + const val IMAGE_BED_URL = "${SERVER_BASE_URL}/emergency/prepareUpload" //一体机DeviceMonitor程序TCP Server IP地址 const val GAS_BASE_IP = "192.168.10.139" //一体机算法程序IP地址 - const val AI_BASE_IP = "192.168.10.139" + const val AI_BASE_IP = GAS_BASE_IP //相机IP const val CAMERA_IP = "192.168.10.137" //主码流 - const val MAIN_RTSP_URL = "rtsp://192.168.10.137:554" + const val MAIN_RTSP_URL = "rtsp://${CAMERA_IP}:554" //子码流 - const val SUB_RTSP_URL = "rtsp://192.168.10.137:554/h265/ch1/sub/av_stream" + const val SUB_RTSP_URL = "${MAIN_RTSP_URL}/h265/ch1/sub/av_stream" const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" const val DEVICE_CONTROL_SERVER_CONFIG = "deviceControlServerConfig" const val ACCOUNT = "account" 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 e970357..b607548 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 @@ -3,4 +3,7 @@ object RuntimeCache { var projectId = "" var userHelmetCode = "" + var uploadFileTaskId = "" + var imageArray = ArrayList>() + var imageId = "" } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { 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 new file mode 100644 index 0000000..e7b9477 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt @@ -0,0 +1,68 @@ +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/util/HttpRequestHelper.kt b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt new file mode 100644 index 0000000..e522224 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt @@ -0,0 +1,132 @@ +package com.casic.br.operationsite.test.util + +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.lifecycleScope +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.pengxh.kt.lite.utils.Constant +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.logging.HttpLoggingInterceptor +import java.io.IOException +import java.util.concurrent.TimeUnit + +/** + * Service里面的Http请求 + * */ +class HttpRequestHelper(builder: Builder) : LifecycleOwner { + + private val kTag = "HttpRequestHelper" + private val registry = LifecycleRegistry(this) + private val gson by lazy { Gson() } + + class Builder { + lateinit var key: String + lateinit var value: String + lateinit var map: HashMap + lateinit var url: String + lateinit var httpRequestCallback: OnHttpRequestCallback + + /** + * 设置网络请求鉴权 + */ + fun setAuthentication(key: String = "token", value: String = ""): Builder { + this.key = key + this.value = value + return this + } + + /** + * 设置网络请求参数 + * */ + fun setRequestParam(map: HashMap): Builder { + this.map = map + return this + } + + /** + * 设置网络请求接口地址 + * */ + fun setRequestTarget(url: String): Builder { + this.url = url + return this + } + + /** + * 设置网络请求回调监听 + * */ + fun setOnHttpRequestCallback(httpRequestCallback: OnHttpRequestCallback): Builder { + this.httpRequestCallback = httpRequestCallback + return this + } + + fun build(): HttpRequestHelper { + return HttpRequestHelper(this) + } + } + + private val key = builder.key + private val value = builder.value + private val map = builder.map + private val url = builder.url + private val callback = builder.httpRequestCallback + + /** + * 发起网络请求 + * */ + fun start() { + val param = JsonObject() + map.forEach { + param.add(it.key, gson.toJsonTree(it.value)) + } + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + //构建Request + val request = Request.Builder().addHeader(key, value).post(requestBody).url(url).build() + lifecycleScope.launch(Dispatchers.IO) { + val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(interceptor) + .readTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .build() + try { + val response = client.newCall(request).execute() + response.body?.apply { + withContext(Dispatchers.Main) { + callback.onSuccess(string()) + } + } + } catch (e: IOException) { + withContext(Dispatchers.Main) { + callback.onFailure(e) + } + } + } + } + + interface OnHttpRequestCallback { + fun onSuccess(result: String) + + fun onFailure(throwable: Throwable) + } + + override fun getLifecycle(): Lifecycle { + return registry + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt index ba40569..34e438c 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt @@ -29,21 +29,22 @@ } const val SERVER_BASE_URL = "http://111.198.10.15:22006" + const val IMAGE_BED_URL = "${SERVER_BASE_URL}/emergency/prepareUpload" //一体机DeviceMonitor程序TCP Server IP地址 const val GAS_BASE_IP = "192.168.10.139" //一体机算法程序IP地址 - const val AI_BASE_IP = "192.168.10.139" + const val AI_BASE_IP = GAS_BASE_IP //相机IP const val CAMERA_IP = "192.168.10.137" //主码流 - const val MAIN_RTSP_URL = "rtsp://192.168.10.137:554" + const val MAIN_RTSP_URL = "rtsp://${CAMERA_IP}:554" //子码流 - const val SUB_RTSP_URL = "rtsp://192.168.10.137:554/h265/ch1/sub/av_stream" + const val SUB_RTSP_URL = "${MAIN_RTSP_URL}/h265/ch1/sub/av_stream" const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" const val DEVICE_CONTROL_SERVER_CONFIG = "deviceControlServerConfig" const val ACCOUNT = "account" 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 e970357..b607548 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 @@ -3,4 +3,7 @@ object RuntimeCache { var projectId = "" var userHelmetCode = "" + var uploadFileTaskId = "" + var imageArray = ArrayList>() + var imageId = "" } \ 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 9c774c7..24bef6b 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 @@ -25,8 +25,8 @@ import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.tcp.SocketManager -import com.casic.br.operationsite.test.vm.ConstructionCheckViewModel import com.casic.br.operationsite.test.vm.UploadFileViewModel import com.google.common.util.concurrent.ListenableFuture import com.luck.picture.lib.basic.PictureSelector @@ -52,6 +52,7 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale +import java.util.UUID import java.util.concurrent.ExecutionException import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -74,10 +75,10 @@ private lateinit var imageAnalysis: ImageAnalysis private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var imageAdapter: EditableImageAdapter - private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 private var isStart = false + private var index = 1 override fun initEvent() { binding.startCheckButton.setOnClickListener { @@ -151,7 +152,6 @@ } //发送指令 SocketManager.get.send(LocaleConstant.END_CONSTRUCTION_COMMAND) -// constructionCheckViewModel.uploadPhaseData(this, "brief", imagePaths, arrayListOf()) navigatePageTo() } } @@ -172,7 +172,7 @@ }, ContextCompat.getMainExecutor(this)) val viewWidth = getScreenWidth() - (15 + 15).dp2px(this) - imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 3, 3) + imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 2, 2) binding.recyclerView.addItemDecoration( RecyclerViewItemOffsets(marginOffset, marginOffset, marginOffset, marginOffset) ) @@ -183,21 +183,23 @@ if (it.code == 200) { val path = it.data.toString() if (path.isNotBlank()) { + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "brief" + map["image"] = path + map["index"] = index.toString() + map["base64"] = "" + RuntimeCache.imageArray.add(map) + index++ + val url = path.combineImagePath() - Log.d(kTag, "url: $url") imagePaths.add(path) recyclerViewImages.add(url) imageAdapter.notifyDataSetChanged() } } } - -// constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } } private fun bindPreview(cameraProvider: ProcessCameraProvider) { @@ -324,13 +326,6 @@ } } } - -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } } override fun setupTopBarLayout() { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { 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 new file mode 100644 index 0000000..e7b9477 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt @@ -0,0 +1,68 @@ +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/util/HttpRequestHelper.kt b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt new file mode 100644 index 0000000..e522224 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt @@ -0,0 +1,132 @@ +package com.casic.br.operationsite.test.util + +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.lifecycleScope +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.pengxh.kt.lite.utils.Constant +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.logging.HttpLoggingInterceptor +import java.io.IOException +import java.util.concurrent.TimeUnit + +/** + * Service里面的Http请求 + * */ +class HttpRequestHelper(builder: Builder) : LifecycleOwner { + + private val kTag = "HttpRequestHelper" + private val registry = LifecycleRegistry(this) + private val gson by lazy { Gson() } + + class Builder { + lateinit var key: String + lateinit var value: String + lateinit var map: HashMap + lateinit var url: String + lateinit var httpRequestCallback: OnHttpRequestCallback + + /** + * 设置网络请求鉴权 + */ + fun setAuthentication(key: String = "token", value: String = ""): Builder { + this.key = key + this.value = value + return this + } + + /** + * 设置网络请求参数 + * */ + fun setRequestParam(map: HashMap): Builder { + this.map = map + return this + } + + /** + * 设置网络请求接口地址 + * */ + fun setRequestTarget(url: String): Builder { + this.url = url + return this + } + + /** + * 设置网络请求回调监听 + * */ + fun setOnHttpRequestCallback(httpRequestCallback: OnHttpRequestCallback): Builder { + this.httpRequestCallback = httpRequestCallback + return this + } + + fun build(): HttpRequestHelper { + return HttpRequestHelper(this) + } + } + + private val key = builder.key + private val value = builder.value + private val map = builder.map + private val url = builder.url + private val callback = builder.httpRequestCallback + + /** + * 发起网络请求 + * */ + fun start() { + val param = JsonObject() + map.forEach { + param.add(it.key, gson.toJsonTree(it.value)) + } + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + //构建Request + val request = Request.Builder().addHeader(key, value).post(requestBody).url(url).build() + lifecycleScope.launch(Dispatchers.IO) { + val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(interceptor) + .readTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .build() + try { + val response = client.newCall(request).execute() + response.body?.apply { + withContext(Dispatchers.Main) { + callback.onSuccess(string()) + } + } + } catch (e: IOException) { + withContext(Dispatchers.Main) { + callback.onFailure(e) + } + } + } + } + + interface OnHttpRequestCallback { + fun onSuccess(result: String) + + fun onFailure(throwable: Throwable) + } + + override fun getLifecycle(): Lifecycle { + return registry + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt index ba40569..34e438c 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt @@ -29,21 +29,22 @@ } const val SERVER_BASE_URL = "http://111.198.10.15:22006" + const val IMAGE_BED_URL = "${SERVER_BASE_URL}/emergency/prepareUpload" //一体机DeviceMonitor程序TCP Server IP地址 const val GAS_BASE_IP = "192.168.10.139" //一体机算法程序IP地址 - const val AI_BASE_IP = "192.168.10.139" + const val AI_BASE_IP = GAS_BASE_IP //相机IP const val CAMERA_IP = "192.168.10.137" //主码流 - const val MAIN_RTSP_URL = "rtsp://192.168.10.137:554" + const val MAIN_RTSP_URL = "rtsp://${CAMERA_IP}:554" //子码流 - const val SUB_RTSP_URL = "rtsp://192.168.10.137:554/h265/ch1/sub/av_stream" + const val SUB_RTSP_URL = "${MAIN_RTSP_URL}/h265/ch1/sub/av_stream" const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" const val DEVICE_CONTROL_SERVER_CONFIG = "deviceControlServerConfig" const val ACCOUNT = "account" 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 e970357..b607548 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 @@ -3,4 +3,7 @@ object RuntimeCache { var projectId = "" var userHelmetCode = "" + var uploadFileTaskId = "" + var imageArray = ArrayList>() + var imageId = "" } \ 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 9c774c7..24bef6b 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 @@ -25,8 +25,8 @@ import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.tcp.SocketManager -import com.casic.br.operationsite.test.vm.ConstructionCheckViewModel import com.casic.br.operationsite.test.vm.UploadFileViewModel import com.google.common.util.concurrent.ListenableFuture import com.luck.picture.lib.basic.PictureSelector @@ -52,6 +52,7 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale +import java.util.UUID import java.util.concurrent.ExecutionException import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -74,10 +75,10 @@ private lateinit var imageAnalysis: ImageAnalysis private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var imageAdapter: EditableImageAdapter - private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 private var isStart = false + private var index = 1 override fun initEvent() { binding.startCheckButton.setOnClickListener { @@ -151,7 +152,6 @@ } //发送指令 SocketManager.get.send(LocaleConstant.END_CONSTRUCTION_COMMAND) -// constructionCheckViewModel.uploadPhaseData(this, "brief", imagePaths, arrayListOf()) navigatePageTo() } } @@ -172,7 +172,7 @@ }, ContextCompat.getMainExecutor(this)) val viewWidth = getScreenWidth() - (15 + 15).dp2px(this) - imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 3, 3) + imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 2, 2) binding.recyclerView.addItemDecoration( RecyclerViewItemOffsets(marginOffset, marginOffset, marginOffset, marginOffset) ) @@ -183,21 +183,23 @@ if (it.code == 200) { val path = it.data.toString() if (path.isNotBlank()) { + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "brief" + map["image"] = path + map["index"] = index.toString() + map["base64"] = "" + RuntimeCache.imageArray.add(map) + index++ + val url = path.combineImagePath() - Log.d(kTag, "url: $url") imagePaths.add(path) recyclerViewImages.add(url) imageAdapter.notifyDataSetChanged() } } } - -// constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } } private fun bindPreview(cameraProvider: ProcessCameraProvider) { @@ -324,13 +326,6 @@ } } } - -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } } override fun setupTopBarLayout() { 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 af0849b..a9d448d 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 @@ -41,6 +41,7 @@ import java.util.Locale import java.util.Timer import java.util.TimerTask +import java.util.UUID import java.util.concurrent.TimeUnit @@ -49,7 +50,6 @@ private val kTag = "EnvironmentActivity" private val context = this private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val base64Array: ArrayList = ArrayList() private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var workSiteViewModel: WorkSiteViewModel @@ -59,6 +59,7 @@ 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 { @@ -68,7 +69,19 @@ LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { try { val base64 = msg.obj as String - base64Array.add(base64) + + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "before_operation_environment" + map["image"] = "" + map["index"] = "1" + map["base64"] = base64 + if (!isDone) { + RuntimeCache.imageArray.add(map) + isDone = true + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) binding.blowerImageView.setImageBitmap(bitmap) @@ -92,7 +105,7 @@ } SocketManager.get.send(LocaleConstant.START_ENV_COMMAND) constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "before_operation_environment" + LocaleConstant.AI_BASE_IP, "before_operation_environment" ) } @@ -140,9 +153,6 @@ return@setOnClickListener } SocketManager.get.send(LocaleConstant.END_ENV_COMMAND) -// constructionCheckViewModel.uploadPhaseData( -// this, "before_operation_environment", arrayListOf(), base64Array -// ) navigatePageTo() } } @@ -152,11 +162,6 @@ weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } //动态设置rtspPlayerView宽高 val params = binding.rtspPlayerView.layoutParams as LinearLayout.LayoutParams @@ -166,8 +171,7 @@ params.height = videoHeight.toInt() binding.rtspPlayerView.layoutParams = params VideoPlayerManager.setGSYVideoPlayerOptions( - binding.rtspPlayerView, - LocaleConstant.SUB_RTSP_URL + binding.rtspPlayerView, LocaleConstant.SUB_RTSP_URL ) workSiteViewModel = ViewModelProvider(this)[WorkSiteViewModel::class.java] @@ -260,12 +264,7 @@ } override fun observeRequestState() { -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } + } override fun setupTopBarLayout() { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { 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 new file mode 100644 index 0000000..e7b9477 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt @@ -0,0 +1,68 @@ +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/util/HttpRequestHelper.kt b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt new file mode 100644 index 0000000..e522224 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt @@ -0,0 +1,132 @@ +package com.casic.br.operationsite.test.util + +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.lifecycleScope +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.pengxh.kt.lite.utils.Constant +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.logging.HttpLoggingInterceptor +import java.io.IOException +import java.util.concurrent.TimeUnit + +/** + * Service里面的Http请求 + * */ +class HttpRequestHelper(builder: Builder) : LifecycleOwner { + + private val kTag = "HttpRequestHelper" + private val registry = LifecycleRegistry(this) + private val gson by lazy { Gson() } + + class Builder { + lateinit var key: String + lateinit var value: String + lateinit var map: HashMap + lateinit var url: String + lateinit var httpRequestCallback: OnHttpRequestCallback + + /** + * 设置网络请求鉴权 + */ + fun setAuthentication(key: String = "token", value: String = ""): Builder { + this.key = key + this.value = value + return this + } + + /** + * 设置网络请求参数 + * */ + fun setRequestParam(map: HashMap): Builder { + this.map = map + return this + } + + /** + * 设置网络请求接口地址 + * */ + fun setRequestTarget(url: String): Builder { + this.url = url + return this + } + + /** + * 设置网络请求回调监听 + * */ + fun setOnHttpRequestCallback(httpRequestCallback: OnHttpRequestCallback): Builder { + this.httpRequestCallback = httpRequestCallback + return this + } + + fun build(): HttpRequestHelper { + return HttpRequestHelper(this) + } + } + + private val key = builder.key + private val value = builder.value + private val map = builder.map + private val url = builder.url + private val callback = builder.httpRequestCallback + + /** + * 发起网络请求 + * */ + fun start() { + val param = JsonObject() + map.forEach { + param.add(it.key, gson.toJsonTree(it.value)) + } + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + //构建Request + val request = Request.Builder().addHeader(key, value).post(requestBody).url(url).build() + lifecycleScope.launch(Dispatchers.IO) { + val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(interceptor) + .readTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .build() + try { + val response = client.newCall(request).execute() + response.body?.apply { + withContext(Dispatchers.Main) { + callback.onSuccess(string()) + } + } + } catch (e: IOException) { + withContext(Dispatchers.Main) { + callback.onFailure(e) + } + } + } + } + + interface OnHttpRequestCallback { + fun onSuccess(result: String) + + fun onFailure(throwable: Throwable) + } + + override fun getLifecycle(): Lifecycle { + return registry + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt index ba40569..34e438c 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt @@ -29,21 +29,22 @@ } const val SERVER_BASE_URL = "http://111.198.10.15:22006" + const val IMAGE_BED_URL = "${SERVER_BASE_URL}/emergency/prepareUpload" //一体机DeviceMonitor程序TCP Server IP地址 const val GAS_BASE_IP = "192.168.10.139" //一体机算法程序IP地址 - const val AI_BASE_IP = "192.168.10.139" + const val AI_BASE_IP = GAS_BASE_IP //相机IP const val CAMERA_IP = "192.168.10.137" //主码流 - const val MAIN_RTSP_URL = "rtsp://192.168.10.137:554" + const val MAIN_RTSP_URL = "rtsp://${CAMERA_IP}:554" //子码流 - const val SUB_RTSP_URL = "rtsp://192.168.10.137:554/h265/ch1/sub/av_stream" + const val SUB_RTSP_URL = "${MAIN_RTSP_URL}/h265/ch1/sub/av_stream" const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" const val DEVICE_CONTROL_SERVER_CONFIG = "deviceControlServerConfig" const val ACCOUNT = "account" 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 e970357..b607548 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 @@ -3,4 +3,7 @@ object RuntimeCache { var projectId = "" var userHelmetCode = "" + var uploadFileTaskId = "" + var imageArray = ArrayList>() + var imageId = "" } \ 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 9c774c7..24bef6b 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 @@ -25,8 +25,8 @@ import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.tcp.SocketManager -import com.casic.br.operationsite.test.vm.ConstructionCheckViewModel import com.casic.br.operationsite.test.vm.UploadFileViewModel import com.google.common.util.concurrent.ListenableFuture import com.luck.picture.lib.basic.PictureSelector @@ -52,6 +52,7 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale +import java.util.UUID import java.util.concurrent.ExecutionException import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -74,10 +75,10 @@ private lateinit var imageAnalysis: ImageAnalysis private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var imageAdapter: EditableImageAdapter - private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 private var isStart = false + private var index = 1 override fun initEvent() { binding.startCheckButton.setOnClickListener { @@ -151,7 +152,6 @@ } //发送指令 SocketManager.get.send(LocaleConstant.END_CONSTRUCTION_COMMAND) -// constructionCheckViewModel.uploadPhaseData(this, "brief", imagePaths, arrayListOf()) navigatePageTo() } } @@ -172,7 +172,7 @@ }, ContextCompat.getMainExecutor(this)) val viewWidth = getScreenWidth() - (15 + 15).dp2px(this) - imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 3, 3) + imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 2, 2) binding.recyclerView.addItemDecoration( RecyclerViewItemOffsets(marginOffset, marginOffset, marginOffset, marginOffset) ) @@ -183,21 +183,23 @@ if (it.code == 200) { val path = it.data.toString() if (path.isNotBlank()) { + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "brief" + map["image"] = path + map["index"] = index.toString() + map["base64"] = "" + RuntimeCache.imageArray.add(map) + index++ + val url = path.combineImagePath() - Log.d(kTag, "url: $url") imagePaths.add(path) recyclerViewImages.add(url) imageAdapter.notifyDataSetChanged() } } } - -// constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } } private fun bindPreview(cameraProvider: ProcessCameraProvider) { @@ -324,13 +326,6 @@ } } } - -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } } override fun setupTopBarLayout() { 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 af0849b..a9d448d 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 @@ -41,6 +41,7 @@ import java.util.Locale import java.util.Timer import java.util.TimerTask +import java.util.UUID import java.util.concurrent.TimeUnit @@ -49,7 +50,6 @@ private val kTag = "EnvironmentActivity" private val context = this private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val base64Array: ArrayList = ArrayList() private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var workSiteViewModel: WorkSiteViewModel @@ -59,6 +59,7 @@ 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 { @@ -68,7 +69,19 @@ LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { try { val base64 = msg.obj as String - base64Array.add(base64) + + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "before_operation_environment" + map["image"] = "" + map["index"] = "1" + map["base64"] = base64 + if (!isDone) { + RuntimeCache.imageArray.add(map) + isDone = true + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) binding.blowerImageView.setImageBitmap(bitmap) @@ -92,7 +105,7 @@ } SocketManager.get.send(LocaleConstant.START_ENV_COMMAND) constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "before_operation_environment" + LocaleConstant.AI_BASE_IP, "before_operation_environment" ) } @@ -140,9 +153,6 @@ return@setOnClickListener } SocketManager.get.send(LocaleConstant.END_ENV_COMMAND) -// constructionCheckViewModel.uploadPhaseData( -// this, "before_operation_environment", arrayListOf(), base64Array -// ) navigatePageTo() } } @@ -152,11 +162,6 @@ weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } //动态设置rtspPlayerView宽高 val params = binding.rtspPlayerView.layoutParams as LinearLayout.LayoutParams @@ -166,8 +171,7 @@ params.height = videoHeight.toInt() binding.rtspPlayerView.layoutParams = params VideoPlayerManager.setGSYVideoPlayerOptions( - binding.rtspPlayerView, - LocaleConstant.SUB_RTSP_URL + binding.rtspPlayerView, LocaleConstant.SUB_RTSP_URL ) workSiteViewModel = ViewModelProvider(this)[WorkSiteViewModel::class.java] @@ -260,12 +264,7 @@ } override fun observeRequestState() { -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } + } override fun setupTopBarLayout() { 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 ba8427f..4df106e 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 @@ -58,18 +58,18 @@ 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 - private lateinit var timer: Timer - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val marginOffset by lazy { 1.dp2px(this) } - private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 override fun initEvent() { binding.alarmCheckbox.setOnCheckedChangeListener { _, isChecked -> @@ -167,9 +167,7 @@ } binding.startVideoCheckButton.setOnClickListener { - constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "in_operation" - ) + constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "in_operation") } binding.showControlViewButton.setOnClickListener { @@ -414,9 +412,8 @@ AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { isEndTask = true - constructionCheckViewModel.setCurrentPhase( - context, LocaleConstant.AI_BASE_IP, "stop" - ) + RuntimeCache.imageArray.clear() + constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "stop") } override fun onCancelClick() { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { 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 new file mode 100644 index 0000000..e7b9477 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt @@ -0,0 +1,68 @@ +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/util/HttpRequestHelper.kt b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt new file mode 100644 index 0000000..e522224 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt @@ -0,0 +1,132 @@ +package com.casic.br.operationsite.test.util + +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.lifecycleScope +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.pengxh.kt.lite.utils.Constant +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.logging.HttpLoggingInterceptor +import java.io.IOException +import java.util.concurrent.TimeUnit + +/** + * Service里面的Http请求 + * */ +class HttpRequestHelper(builder: Builder) : LifecycleOwner { + + private val kTag = "HttpRequestHelper" + private val registry = LifecycleRegistry(this) + private val gson by lazy { Gson() } + + class Builder { + lateinit var key: String + lateinit var value: String + lateinit var map: HashMap + lateinit var url: String + lateinit var httpRequestCallback: OnHttpRequestCallback + + /** + * 设置网络请求鉴权 + */ + fun setAuthentication(key: String = "token", value: String = ""): Builder { + this.key = key + this.value = value + return this + } + + /** + * 设置网络请求参数 + * */ + fun setRequestParam(map: HashMap): Builder { + this.map = map + return this + } + + /** + * 设置网络请求接口地址 + * */ + fun setRequestTarget(url: String): Builder { + this.url = url + return this + } + + /** + * 设置网络请求回调监听 + * */ + fun setOnHttpRequestCallback(httpRequestCallback: OnHttpRequestCallback): Builder { + this.httpRequestCallback = httpRequestCallback + return this + } + + fun build(): HttpRequestHelper { + return HttpRequestHelper(this) + } + } + + private val key = builder.key + private val value = builder.value + private val map = builder.map + private val url = builder.url + private val callback = builder.httpRequestCallback + + /** + * 发起网络请求 + * */ + fun start() { + val param = JsonObject() + map.forEach { + param.add(it.key, gson.toJsonTree(it.value)) + } + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + //构建Request + val request = Request.Builder().addHeader(key, value).post(requestBody).url(url).build() + lifecycleScope.launch(Dispatchers.IO) { + val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(interceptor) + .readTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .build() + try { + val response = client.newCall(request).execute() + response.body?.apply { + withContext(Dispatchers.Main) { + callback.onSuccess(string()) + } + } + } catch (e: IOException) { + withContext(Dispatchers.Main) { + callback.onFailure(e) + } + } + } + } + + interface OnHttpRequestCallback { + fun onSuccess(result: String) + + fun onFailure(throwable: Throwable) + } + + override fun getLifecycle(): Lifecycle { + return registry + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt index ba40569..34e438c 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt @@ -29,21 +29,22 @@ } const val SERVER_BASE_URL = "http://111.198.10.15:22006" + const val IMAGE_BED_URL = "${SERVER_BASE_URL}/emergency/prepareUpload" //一体机DeviceMonitor程序TCP Server IP地址 const val GAS_BASE_IP = "192.168.10.139" //一体机算法程序IP地址 - const val AI_BASE_IP = "192.168.10.139" + const val AI_BASE_IP = GAS_BASE_IP //相机IP const val CAMERA_IP = "192.168.10.137" //主码流 - const val MAIN_RTSP_URL = "rtsp://192.168.10.137:554" + const val MAIN_RTSP_URL = "rtsp://${CAMERA_IP}:554" //子码流 - const val SUB_RTSP_URL = "rtsp://192.168.10.137:554/h265/ch1/sub/av_stream" + const val SUB_RTSP_URL = "${MAIN_RTSP_URL}/h265/ch1/sub/av_stream" const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" const val DEVICE_CONTROL_SERVER_CONFIG = "deviceControlServerConfig" const val ACCOUNT = "account" 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 e970357..b607548 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 @@ -3,4 +3,7 @@ object RuntimeCache { var projectId = "" var userHelmetCode = "" + var uploadFileTaskId = "" + var imageArray = ArrayList>() + var imageId = "" } \ 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 9c774c7..24bef6b 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 @@ -25,8 +25,8 @@ import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.tcp.SocketManager -import com.casic.br.operationsite.test.vm.ConstructionCheckViewModel import com.casic.br.operationsite.test.vm.UploadFileViewModel import com.google.common.util.concurrent.ListenableFuture import com.luck.picture.lib.basic.PictureSelector @@ -52,6 +52,7 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale +import java.util.UUID import java.util.concurrent.ExecutionException import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -74,10 +75,10 @@ private lateinit var imageAnalysis: ImageAnalysis private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var imageAdapter: EditableImageAdapter - private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 private var isStart = false + private var index = 1 override fun initEvent() { binding.startCheckButton.setOnClickListener { @@ -151,7 +152,6 @@ } //发送指令 SocketManager.get.send(LocaleConstant.END_CONSTRUCTION_COMMAND) -// constructionCheckViewModel.uploadPhaseData(this, "brief", imagePaths, arrayListOf()) navigatePageTo() } } @@ -172,7 +172,7 @@ }, ContextCompat.getMainExecutor(this)) val viewWidth = getScreenWidth() - (15 + 15).dp2px(this) - imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 3, 3) + imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 2, 2) binding.recyclerView.addItemDecoration( RecyclerViewItemOffsets(marginOffset, marginOffset, marginOffset, marginOffset) ) @@ -183,21 +183,23 @@ if (it.code == 200) { val path = it.data.toString() if (path.isNotBlank()) { + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "brief" + map["image"] = path + map["index"] = index.toString() + map["base64"] = "" + RuntimeCache.imageArray.add(map) + index++ + val url = path.combineImagePath() - Log.d(kTag, "url: $url") imagePaths.add(path) recyclerViewImages.add(url) imageAdapter.notifyDataSetChanged() } } } - -// constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } } private fun bindPreview(cameraProvider: ProcessCameraProvider) { @@ -324,13 +326,6 @@ } } } - -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } } override fun setupTopBarLayout() { 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 af0849b..a9d448d 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 @@ -41,6 +41,7 @@ import java.util.Locale import java.util.Timer import java.util.TimerTask +import java.util.UUID import java.util.concurrent.TimeUnit @@ -49,7 +50,6 @@ private val kTag = "EnvironmentActivity" private val context = this private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val base64Array: ArrayList = ArrayList() private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var workSiteViewModel: WorkSiteViewModel @@ -59,6 +59,7 @@ 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 { @@ -68,7 +69,19 @@ LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { try { val base64 = msg.obj as String - base64Array.add(base64) + + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "before_operation_environment" + map["image"] = "" + map["index"] = "1" + map["base64"] = base64 + if (!isDone) { + RuntimeCache.imageArray.add(map) + isDone = true + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) binding.blowerImageView.setImageBitmap(bitmap) @@ -92,7 +105,7 @@ } SocketManager.get.send(LocaleConstant.START_ENV_COMMAND) constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "before_operation_environment" + LocaleConstant.AI_BASE_IP, "before_operation_environment" ) } @@ -140,9 +153,6 @@ return@setOnClickListener } SocketManager.get.send(LocaleConstant.END_ENV_COMMAND) -// constructionCheckViewModel.uploadPhaseData( -// this, "before_operation_environment", arrayListOf(), base64Array -// ) navigatePageTo() } } @@ -152,11 +162,6 @@ weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } //动态设置rtspPlayerView宽高 val params = binding.rtspPlayerView.layoutParams as LinearLayout.LayoutParams @@ -166,8 +171,7 @@ params.height = videoHeight.toInt() binding.rtspPlayerView.layoutParams = params VideoPlayerManager.setGSYVideoPlayerOptions( - binding.rtspPlayerView, - LocaleConstant.SUB_RTSP_URL + binding.rtspPlayerView, LocaleConstant.SUB_RTSP_URL ) workSiteViewModel = ViewModelProvider(this)[WorkSiteViewModel::class.java] @@ -260,12 +264,7 @@ } override fun observeRequestState() { -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } + } override fun setupTopBarLayout() { 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 ba8427f..4df106e 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 @@ -58,18 +58,18 @@ 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 - private lateinit var timer: Timer - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val marginOffset by lazy { 1.dp2px(this) } - private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 override fun initEvent() { binding.alarmCheckbox.setOnCheckedChangeListener { _, isChecked -> @@ -167,9 +167,7 @@ } binding.startVideoCheckButton.setOnClickListener { - constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "in_operation" - ) + constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "in_operation") } binding.showControlViewButton.setOnClickListener { @@ -414,9 +412,8 @@ AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { isEndTask = true - constructionCheckViewModel.setCurrentPhase( - context, LocaleConstant.AI_BASE_IP, "stop" - ) + RuntimeCache.imageArray.clear() + constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "stop") } override fun onCancelClick() { 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 1156373..2fa7b4a 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 @@ -15,6 +15,7 @@ import com.casic.br.operationsite.test.databinding.ActivitySuppliesBinding import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager import com.casic.br.operationsite.test.util.tcp.SocketManager import com.casic.br.operationsite.test.vm.ConstructionCheckViewModel @@ -47,22 +48,23 @@ 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 { 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 imageAdapter: EditableImageAdapter private lateinit var timer: Timer private var webSocket: WebSocket? = null private var isWebSocketConnected = false - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val marginOffset by lazy { 1.dp2px(this) } - private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 - private val base64Array: ArrayList = ArrayList() + private var index = 1 override fun initEvent() { binding.startSuppliesCheckButton.setOnClickListener { @@ -74,7 +76,7 @@ SocketManager.get.send(LocaleConstant.START_SUPPLIES_COMMAND) delay(2000) constructionCheckViewModel.setCurrentPhase( - context, LocaleConstant.AI_BASE_IP, "before_operation_protection" + LocaleConstant.AI_BASE_IP, "before_operation_protection" ) withContext(Dispatchers.Main) { binding.stepView.text = "稍后开始检查第一项:四合一,请准备" @@ -86,10 +88,6 @@ BottomControlSheet(this).show() } -// binding.startVideoCheckButton.setOnClickListener { -// startVideoLauncher.launch(Intent(this, HelmetVideoActivity::class.java)) -// } - imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { "当前模式不支持手动添加图片".show(context) @@ -115,9 +113,6 @@ .setPositiveButton("确定").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { -// constructionCheckViewModel.uploadPhaseData( -// context, "before_operation_protection", arrayListOf(), base64Array -// ) SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) navigatePageTo() } @@ -133,9 +128,8 @@ private val startVideoLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { - Log.d(kTag, "startVideoLauncher: ") constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "before_operation_protection" + LocaleConstant.AI_BASE_IP, "before_operation_protection" ) binding.stepView.text = "稍后开始检查第一项:四合一,请准备" } @@ -183,12 +177,6 @@ weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) -// navigatePageTo() -// } -// } //动态设置rtspPlayerView宽高 val params = binding.rtspPlayerView.layoutParams as LinearLayout.LayoutParams @@ -226,7 +214,17 @@ LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { try { val base64 = msg.obj as String - base64Array.add(base64) + + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "before_operation_protection" + map["image"] = "" + map["index"] = index.toString() + map["base64"] = base64 + RuntimeCache.imageArray.add(map) + index++ + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) val imagePath = "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" @@ -248,10 +246,6 @@ .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { -// constructionCheckViewModel.uploadPhaseData( -// context, "before_operation_protection", -// arrayListOf(), base64Array -// ) SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) navigatePageTo() } @@ -277,12 +271,7 @@ } override fun observeRequestState() { -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } + } override fun setupTopBarLayout() { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { 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 new file mode 100644 index 0000000..e7b9477 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt @@ -0,0 +1,68 @@ +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/util/HttpRequestHelper.kt b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt new file mode 100644 index 0000000..e522224 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt @@ -0,0 +1,132 @@ +package com.casic.br.operationsite.test.util + +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.lifecycleScope +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.pengxh.kt.lite.utils.Constant +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.logging.HttpLoggingInterceptor +import java.io.IOException +import java.util.concurrent.TimeUnit + +/** + * Service里面的Http请求 + * */ +class HttpRequestHelper(builder: Builder) : LifecycleOwner { + + private val kTag = "HttpRequestHelper" + private val registry = LifecycleRegistry(this) + private val gson by lazy { Gson() } + + class Builder { + lateinit var key: String + lateinit var value: String + lateinit var map: HashMap + lateinit var url: String + lateinit var httpRequestCallback: OnHttpRequestCallback + + /** + * 设置网络请求鉴权 + */ + fun setAuthentication(key: String = "token", value: String = ""): Builder { + this.key = key + this.value = value + return this + } + + /** + * 设置网络请求参数 + * */ + fun setRequestParam(map: HashMap): Builder { + this.map = map + return this + } + + /** + * 设置网络请求接口地址 + * */ + fun setRequestTarget(url: String): Builder { + this.url = url + return this + } + + /** + * 设置网络请求回调监听 + * */ + fun setOnHttpRequestCallback(httpRequestCallback: OnHttpRequestCallback): Builder { + this.httpRequestCallback = httpRequestCallback + return this + } + + fun build(): HttpRequestHelper { + return HttpRequestHelper(this) + } + } + + private val key = builder.key + private val value = builder.value + private val map = builder.map + private val url = builder.url + private val callback = builder.httpRequestCallback + + /** + * 发起网络请求 + * */ + fun start() { + val param = JsonObject() + map.forEach { + param.add(it.key, gson.toJsonTree(it.value)) + } + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + //构建Request + val request = Request.Builder().addHeader(key, value).post(requestBody).url(url).build() + lifecycleScope.launch(Dispatchers.IO) { + val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(interceptor) + .readTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .build() + try { + val response = client.newCall(request).execute() + response.body?.apply { + withContext(Dispatchers.Main) { + callback.onSuccess(string()) + } + } + } catch (e: IOException) { + withContext(Dispatchers.Main) { + callback.onFailure(e) + } + } + } + } + + interface OnHttpRequestCallback { + fun onSuccess(result: String) + + fun onFailure(throwable: Throwable) + } + + override fun getLifecycle(): Lifecycle { + return registry + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt index ba40569..34e438c 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt @@ -29,21 +29,22 @@ } const val SERVER_BASE_URL = "http://111.198.10.15:22006" + const val IMAGE_BED_URL = "${SERVER_BASE_URL}/emergency/prepareUpload" //一体机DeviceMonitor程序TCP Server IP地址 const val GAS_BASE_IP = "192.168.10.139" //一体机算法程序IP地址 - const val AI_BASE_IP = "192.168.10.139" + const val AI_BASE_IP = GAS_BASE_IP //相机IP const val CAMERA_IP = "192.168.10.137" //主码流 - const val MAIN_RTSP_URL = "rtsp://192.168.10.137:554" + const val MAIN_RTSP_URL = "rtsp://${CAMERA_IP}:554" //子码流 - const val SUB_RTSP_URL = "rtsp://192.168.10.137:554/h265/ch1/sub/av_stream" + const val SUB_RTSP_URL = "${MAIN_RTSP_URL}/h265/ch1/sub/av_stream" const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" const val DEVICE_CONTROL_SERVER_CONFIG = "deviceControlServerConfig" const val ACCOUNT = "account" 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 e970357..b607548 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 @@ -3,4 +3,7 @@ object RuntimeCache { var projectId = "" var userHelmetCode = "" + var uploadFileTaskId = "" + var imageArray = ArrayList>() + var imageId = "" } \ 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 9c774c7..24bef6b 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 @@ -25,8 +25,8 @@ import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.tcp.SocketManager -import com.casic.br.operationsite.test.vm.ConstructionCheckViewModel import com.casic.br.operationsite.test.vm.UploadFileViewModel import com.google.common.util.concurrent.ListenableFuture import com.luck.picture.lib.basic.PictureSelector @@ -52,6 +52,7 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale +import java.util.UUID import java.util.concurrent.ExecutionException import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -74,10 +75,10 @@ private lateinit var imageAnalysis: ImageAnalysis private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var imageAdapter: EditableImageAdapter - private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 private var isStart = false + private var index = 1 override fun initEvent() { binding.startCheckButton.setOnClickListener { @@ -151,7 +152,6 @@ } //发送指令 SocketManager.get.send(LocaleConstant.END_CONSTRUCTION_COMMAND) -// constructionCheckViewModel.uploadPhaseData(this, "brief", imagePaths, arrayListOf()) navigatePageTo() } } @@ -172,7 +172,7 @@ }, ContextCompat.getMainExecutor(this)) val viewWidth = getScreenWidth() - (15 + 15).dp2px(this) - imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 3, 3) + imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 2, 2) binding.recyclerView.addItemDecoration( RecyclerViewItemOffsets(marginOffset, marginOffset, marginOffset, marginOffset) ) @@ -183,21 +183,23 @@ if (it.code == 200) { val path = it.data.toString() if (path.isNotBlank()) { + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "brief" + map["image"] = path + map["index"] = index.toString() + map["base64"] = "" + RuntimeCache.imageArray.add(map) + index++ + val url = path.combineImagePath() - Log.d(kTag, "url: $url") imagePaths.add(path) recyclerViewImages.add(url) imageAdapter.notifyDataSetChanged() } } } - -// constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } } private fun bindPreview(cameraProvider: ProcessCameraProvider) { @@ -324,13 +326,6 @@ } } } - -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } } override fun setupTopBarLayout() { 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 af0849b..a9d448d 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 @@ -41,6 +41,7 @@ import java.util.Locale import java.util.Timer import java.util.TimerTask +import java.util.UUID import java.util.concurrent.TimeUnit @@ -49,7 +50,6 @@ private val kTag = "EnvironmentActivity" private val context = this private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val base64Array: ArrayList = ArrayList() private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var workSiteViewModel: WorkSiteViewModel @@ -59,6 +59,7 @@ 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 { @@ -68,7 +69,19 @@ LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { try { val base64 = msg.obj as String - base64Array.add(base64) + + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "before_operation_environment" + map["image"] = "" + map["index"] = "1" + map["base64"] = base64 + if (!isDone) { + RuntimeCache.imageArray.add(map) + isDone = true + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) binding.blowerImageView.setImageBitmap(bitmap) @@ -92,7 +105,7 @@ } SocketManager.get.send(LocaleConstant.START_ENV_COMMAND) constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "before_operation_environment" + LocaleConstant.AI_BASE_IP, "before_operation_environment" ) } @@ -140,9 +153,6 @@ return@setOnClickListener } SocketManager.get.send(LocaleConstant.END_ENV_COMMAND) -// constructionCheckViewModel.uploadPhaseData( -// this, "before_operation_environment", arrayListOf(), base64Array -// ) navigatePageTo() } } @@ -152,11 +162,6 @@ weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } //动态设置rtspPlayerView宽高 val params = binding.rtspPlayerView.layoutParams as LinearLayout.LayoutParams @@ -166,8 +171,7 @@ params.height = videoHeight.toInt() binding.rtspPlayerView.layoutParams = params VideoPlayerManager.setGSYVideoPlayerOptions( - binding.rtspPlayerView, - LocaleConstant.SUB_RTSP_URL + binding.rtspPlayerView, LocaleConstant.SUB_RTSP_URL ) workSiteViewModel = ViewModelProvider(this)[WorkSiteViewModel::class.java] @@ -260,12 +264,7 @@ } override fun observeRequestState() { -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } + } override fun setupTopBarLayout() { 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 ba8427f..4df106e 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 @@ -58,18 +58,18 @@ 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 - private lateinit var timer: Timer - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val marginOffset by lazy { 1.dp2px(this) } - private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 override fun initEvent() { binding.alarmCheckbox.setOnCheckedChangeListener { _, isChecked -> @@ -167,9 +167,7 @@ } binding.startVideoCheckButton.setOnClickListener { - constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "in_operation" - ) + constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "in_operation") } binding.showControlViewButton.setOnClickListener { @@ -414,9 +412,8 @@ AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { isEndTask = true - constructionCheckViewModel.setCurrentPhase( - context, LocaleConstant.AI_BASE_IP, "stop" - ) + RuntimeCache.imageArray.clear() + constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "stop") } override fun onCancelClick() { 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 1156373..2fa7b4a 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 @@ -15,6 +15,7 @@ import com.casic.br.operationsite.test.databinding.ActivitySuppliesBinding import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager import com.casic.br.operationsite.test.util.tcp.SocketManager import com.casic.br.operationsite.test.vm.ConstructionCheckViewModel @@ -47,22 +48,23 @@ 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 { 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 imageAdapter: EditableImageAdapter private lateinit var timer: Timer private var webSocket: WebSocket? = null private var isWebSocketConnected = false - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val marginOffset by lazy { 1.dp2px(this) } - private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 - private val base64Array: ArrayList = ArrayList() + private var index = 1 override fun initEvent() { binding.startSuppliesCheckButton.setOnClickListener { @@ -74,7 +76,7 @@ SocketManager.get.send(LocaleConstant.START_SUPPLIES_COMMAND) delay(2000) constructionCheckViewModel.setCurrentPhase( - context, LocaleConstant.AI_BASE_IP, "before_operation_protection" + LocaleConstant.AI_BASE_IP, "before_operation_protection" ) withContext(Dispatchers.Main) { binding.stepView.text = "稍后开始检查第一项:四合一,请准备" @@ -86,10 +88,6 @@ BottomControlSheet(this).show() } -// binding.startVideoCheckButton.setOnClickListener { -// startVideoLauncher.launch(Intent(this, HelmetVideoActivity::class.java)) -// } - imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { "当前模式不支持手动添加图片".show(context) @@ -115,9 +113,6 @@ .setPositiveButton("确定").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { -// constructionCheckViewModel.uploadPhaseData( -// context, "before_operation_protection", arrayListOf(), base64Array -// ) SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) navigatePageTo() } @@ -133,9 +128,8 @@ private val startVideoLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { - Log.d(kTag, "startVideoLauncher: ") constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "before_operation_protection" + LocaleConstant.AI_BASE_IP, "before_operation_protection" ) binding.stepView.text = "稍后开始检查第一项:四合一,请准备" } @@ -183,12 +177,6 @@ weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) -// navigatePageTo() -// } -// } //动态设置rtspPlayerView宽高 val params = binding.rtspPlayerView.layoutParams as LinearLayout.LayoutParams @@ -226,7 +214,17 @@ LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { try { val base64 = msg.obj as String - base64Array.add(base64) + + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "before_operation_protection" + map["image"] = "" + map["index"] = index.toString() + map["base64"] = base64 + RuntimeCache.imageArray.add(map) + index++ + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) val imagePath = "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" @@ -248,10 +246,6 @@ .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { -// constructionCheckViewModel.uploadPhaseData( -// context, "before_operation_protection", -// arrayListOf(), base64Array -// ) SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) navigatePageTo() } @@ -277,12 +271,7 @@ } override fun observeRequestState() { -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } + } override fun setupTopBarLayout() { 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 e848422..0721c79 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,6 +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.util.AuthenticationHelper import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.vm.LoginViewModel @@ -64,6 +65,7 @@ weakReferenceHandler = WeakReferenceHandler(this) startService(Intent(this, TcpMessageService::class.java)) + startService(Intent(this, UploadImageService::class.java)) workSiteViewModel = ViewModelProvider(this)[WorkSiteViewModel::class.java] getProjectListByPage() @@ -141,6 +143,7 @@ position: Int, t: WorkSiteListModel.DataModel.RowsModel ) { RuntimeCache.projectId = t.id + RuntimeCache.uploadFileTaskId = System.currentTimeMillis().toString() navigatePageTo() } }) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { 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 new file mode 100644 index 0000000..e7b9477 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt @@ -0,0 +1,68 @@ +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/util/HttpRequestHelper.kt b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt new file mode 100644 index 0000000..e522224 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt @@ -0,0 +1,132 @@ +package com.casic.br.operationsite.test.util + +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.lifecycleScope +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.pengxh.kt.lite.utils.Constant +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.logging.HttpLoggingInterceptor +import java.io.IOException +import java.util.concurrent.TimeUnit + +/** + * Service里面的Http请求 + * */ +class HttpRequestHelper(builder: Builder) : LifecycleOwner { + + private val kTag = "HttpRequestHelper" + private val registry = LifecycleRegistry(this) + private val gson by lazy { Gson() } + + class Builder { + lateinit var key: String + lateinit var value: String + lateinit var map: HashMap + lateinit var url: String + lateinit var httpRequestCallback: OnHttpRequestCallback + + /** + * 设置网络请求鉴权 + */ + fun setAuthentication(key: String = "token", value: String = ""): Builder { + this.key = key + this.value = value + return this + } + + /** + * 设置网络请求参数 + * */ + fun setRequestParam(map: HashMap): Builder { + this.map = map + return this + } + + /** + * 设置网络请求接口地址 + * */ + fun setRequestTarget(url: String): Builder { + this.url = url + return this + } + + /** + * 设置网络请求回调监听 + * */ + fun setOnHttpRequestCallback(httpRequestCallback: OnHttpRequestCallback): Builder { + this.httpRequestCallback = httpRequestCallback + return this + } + + fun build(): HttpRequestHelper { + return HttpRequestHelper(this) + } + } + + private val key = builder.key + private val value = builder.value + private val map = builder.map + private val url = builder.url + private val callback = builder.httpRequestCallback + + /** + * 发起网络请求 + * */ + fun start() { + val param = JsonObject() + map.forEach { + param.add(it.key, gson.toJsonTree(it.value)) + } + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + //构建Request + val request = Request.Builder().addHeader(key, value).post(requestBody).url(url).build() + lifecycleScope.launch(Dispatchers.IO) { + val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(interceptor) + .readTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .build() + try { + val response = client.newCall(request).execute() + response.body?.apply { + withContext(Dispatchers.Main) { + callback.onSuccess(string()) + } + } + } catch (e: IOException) { + withContext(Dispatchers.Main) { + callback.onFailure(e) + } + } + } + } + + interface OnHttpRequestCallback { + fun onSuccess(result: String) + + fun onFailure(throwable: Throwable) + } + + override fun getLifecycle(): Lifecycle { + return registry + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt index ba40569..34e438c 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt @@ -29,21 +29,22 @@ } const val SERVER_BASE_URL = "http://111.198.10.15:22006" + const val IMAGE_BED_URL = "${SERVER_BASE_URL}/emergency/prepareUpload" //一体机DeviceMonitor程序TCP Server IP地址 const val GAS_BASE_IP = "192.168.10.139" //一体机算法程序IP地址 - const val AI_BASE_IP = "192.168.10.139" + const val AI_BASE_IP = GAS_BASE_IP //相机IP const val CAMERA_IP = "192.168.10.137" //主码流 - const val MAIN_RTSP_URL = "rtsp://192.168.10.137:554" + const val MAIN_RTSP_URL = "rtsp://${CAMERA_IP}:554" //子码流 - const val SUB_RTSP_URL = "rtsp://192.168.10.137:554/h265/ch1/sub/av_stream" + const val SUB_RTSP_URL = "${MAIN_RTSP_URL}/h265/ch1/sub/av_stream" const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" const val DEVICE_CONTROL_SERVER_CONFIG = "deviceControlServerConfig" const val ACCOUNT = "account" 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 e970357..b607548 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 @@ -3,4 +3,7 @@ object RuntimeCache { var projectId = "" var userHelmetCode = "" + var uploadFileTaskId = "" + var imageArray = ArrayList>() + var imageId = "" } \ 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 9c774c7..24bef6b 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 @@ -25,8 +25,8 @@ import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.tcp.SocketManager -import com.casic.br.operationsite.test.vm.ConstructionCheckViewModel import com.casic.br.operationsite.test.vm.UploadFileViewModel import com.google.common.util.concurrent.ListenableFuture import com.luck.picture.lib.basic.PictureSelector @@ -52,6 +52,7 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale +import java.util.UUID import java.util.concurrent.ExecutionException import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -74,10 +75,10 @@ private lateinit var imageAnalysis: ImageAnalysis private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var imageAdapter: EditableImageAdapter - private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 private var isStart = false + private var index = 1 override fun initEvent() { binding.startCheckButton.setOnClickListener { @@ -151,7 +152,6 @@ } //发送指令 SocketManager.get.send(LocaleConstant.END_CONSTRUCTION_COMMAND) -// constructionCheckViewModel.uploadPhaseData(this, "brief", imagePaths, arrayListOf()) navigatePageTo() } } @@ -172,7 +172,7 @@ }, ContextCompat.getMainExecutor(this)) val viewWidth = getScreenWidth() - (15 + 15).dp2px(this) - imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 3, 3) + imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 2, 2) binding.recyclerView.addItemDecoration( RecyclerViewItemOffsets(marginOffset, marginOffset, marginOffset, marginOffset) ) @@ -183,21 +183,23 @@ if (it.code == 200) { val path = it.data.toString() if (path.isNotBlank()) { + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "brief" + map["image"] = path + map["index"] = index.toString() + map["base64"] = "" + RuntimeCache.imageArray.add(map) + index++ + val url = path.combineImagePath() - Log.d(kTag, "url: $url") imagePaths.add(path) recyclerViewImages.add(url) imageAdapter.notifyDataSetChanged() } } } - -// constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } } private fun bindPreview(cameraProvider: ProcessCameraProvider) { @@ -324,13 +326,6 @@ } } } - -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } } override fun setupTopBarLayout() { 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 af0849b..a9d448d 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 @@ -41,6 +41,7 @@ import java.util.Locale import java.util.Timer import java.util.TimerTask +import java.util.UUID import java.util.concurrent.TimeUnit @@ -49,7 +50,6 @@ private val kTag = "EnvironmentActivity" private val context = this private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val base64Array: ArrayList = ArrayList() private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var workSiteViewModel: WorkSiteViewModel @@ -59,6 +59,7 @@ 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 { @@ -68,7 +69,19 @@ LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { try { val base64 = msg.obj as String - base64Array.add(base64) + + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "before_operation_environment" + map["image"] = "" + map["index"] = "1" + map["base64"] = base64 + if (!isDone) { + RuntimeCache.imageArray.add(map) + isDone = true + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) binding.blowerImageView.setImageBitmap(bitmap) @@ -92,7 +105,7 @@ } SocketManager.get.send(LocaleConstant.START_ENV_COMMAND) constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "before_operation_environment" + LocaleConstant.AI_BASE_IP, "before_operation_environment" ) } @@ -140,9 +153,6 @@ return@setOnClickListener } SocketManager.get.send(LocaleConstant.END_ENV_COMMAND) -// constructionCheckViewModel.uploadPhaseData( -// this, "before_operation_environment", arrayListOf(), base64Array -// ) navigatePageTo() } } @@ -152,11 +162,6 @@ weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } //动态设置rtspPlayerView宽高 val params = binding.rtspPlayerView.layoutParams as LinearLayout.LayoutParams @@ -166,8 +171,7 @@ params.height = videoHeight.toInt() binding.rtspPlayerView.layoutParams = params VideoPlayerManager.setGSYVideoPlayerOptions( - binding.rtspPlayerView, - LocaleConstant.SUB_RTSP_URL + binding.rtspPlayerView, LocaleConstant.SUB_RTSP_URL ) workSiteViewModel = ViewModelProvider(this)[WorkSiteViewModel::class.java] @@ -260,12 +264,7 @@ } override fun observeRequestState() { -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } + } override fun setupTopBarLayout() { 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 ba8427f..4df106e 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 @@ -58,18 +58,18 @@ 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 - private lateinit var timer: Timer - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val marginOffset by lazy { 1.dp2px(this) } - private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 override fun initEvent() { binding.alarmCheckbox.setOnCheckedChangeListener { _, isChecked -> @@ -167,9 +167,7 @@ } binding.startVideoCheckButton.setOnClickListener { - constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "in_operation" - ) + constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "in_operation") } binding.showControlViewButton.setOnClickListener { @@ -414,9 +412,8 @@ AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { isEndTask = true - constructionCheckViewModel.setCurrentPhase( - context, LocaleConstant.AI_BASE_IP, "stop" - ) + RuntimeCache.imageArray.clear() + constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "stop") } override fun onCancelClick() { 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 1156373..2fa7b4a 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 @@ -15,6 +15,7 @@ import com.casic.br.operationsite.test.databinding.ActivitySuppliesBinding import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager import com.casic.br.operationsite.test.util.tcp.SocketManager import com.casic.br.operationsite.test.vm.ConstructionCheckViewModel @@ -47,22 +48,23 @@ 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 { 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 imageAdapter: EditableImageAdapter private lateinit var timer: Timer private var webSocket: WebSocket? = null private var isWebSocketConnected = false - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val marginOffset by lazy { 1.dp2px(this) } - private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 - private val base64Array: ArrayList = ArrayList() + private var index = 1 override fun initEvent() { binding.startSuppliesCheckButton.setOnClickListener { @@ -74,7 +76,7 @@ SocketManager.get.send(LocaleConstant.START_SUPPLIES_COMMAND) delay(2000) constructionCheckViewModel.setCurrentPhase( - context, LocaleConstant.AI_BASE_IP, "before_operation_protection" + LocaleConstant.AI_BASE_IP, "before_operation_protection" ) withContext(Dispatchers.Main) { binding.stepView.text = "稍后开始检查第一项:四合一,请准备" @@ -86,10 +88,6 @@ BottomControlSheet(this).show() } -// binding.startVideoCheckButton.setOnClickListener { -// startVideoLauncher.launch(Intent(this, HelmetVideoActivity::class.java)) -// } - imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { "当前模式不支持手动添加图片".show(context) @@ -115,9 +113,6 @@ .setPositiveButton("确定").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { -// constructionCheckViewModel.uploadPhaseData( -// context, "before_operation_protection", arrayListOf(), base64Array -// ) SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) navigatePageTo() } @@ -133,9 +128,8 @@ private val startVideoLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { - Log.d(kTag, "startVideoLauncher: ") constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "before_operation_protection" + LocaleConstant.AI_BASE_IP, "before_operation_protection" ) binding.stepView.text = "稍后开始检查第一项:四合一,请准备" } @@ -183,12 +177,6 @@ weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) -// navigatePageTo() -// } -// } //动态设置rtspPlayerView宽高 val params = binding.rtspPlayerView.layoutParams as LinearLayout.LayoutParams @@ -226,7 +214,17 @@ LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { try { val base64 = msg.obj as String - base64Array.add(base64) + + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "before_operation_protection" + map["image"] = "" + map["index"] = index.toString() + map["base64"] = base64 + RuntimeCache.imageArray.add(map) + index++ + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) val imagePath = "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" @@ -248,10 +246,6 @@ .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { -// constructionCheckViewModel.uploadPhaseData( -// context, "before_operation_protection", -// arrayListOf(), base64Array -// ) SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) navigatePageTo() } @@ -277,12 +271,7 @@ } override fun observeRequestState() { -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } + } override fun setupTopBarLayout() { 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 e848422..0721c79 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,6 +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.util.AuthenticationHelper import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.vm.LoginViewModel @@ -64,6 +65,7 @@ weakReferenceHandler = WeakReferenceHandler(this) startService(Intent(this, TcpMessageService::class.java)) + startService(Intent(this, UploadImageService::class.java)) workSiteViewModel = ViewModelProvider(this)[WorkSiteViewModel::class.java] getProjectListByPage() @@ -141,6 +143,7 @@ position: Int, t: WorkSiteListModel.DataModel.RowsModel ) { RuntimeCache.projectId = t.id + RuntimeCache.uploadFileTaskId = System.currentTimeMillis().toString() navigatePageTo() } }) diff --git a/app/src/main/java/com/casic/br/operationsite/test/vm/ConstructionCheckViewModel.kt b/app/src/main/java/com/casic/br/operationsite/test/vm/ConstructionCheckViewModel.kt index 760097e..e591d2e 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/vm/ConstructionCheckViewModel.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/vm/ConstructionCheckViewModel.kt @@ -1,20 +1,15 @@ package com.casic.br.operationsite.test.vm -import android.content.Context import androidx.lifecycle.MutableLiveData import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.extensions.getResponseMessage import com.casic.br.operationsite.test.retrofit.RetrofitServiceManager import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch -import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.LoadState class ConstructionCheckViewModel : BaseViewModel() { val setCurrentPhaseResult = MutableLiveData() val setVideoRegionResult = MutableLiveData() - val uploadDataResult = MutableLiveData() fun setVideoRegion(httpConfig: String, position: ArrayList) = launch({ val response = RetrofitServiceManager.setVideoRegion(httpConfig, position) @@ -23,45 +18,10 @@ it.printStackTrace() }) - fun setCurrentPhase(context: Context, httpConfig: String, phase: String) = launch({ - loadState.value = LoadState.Loading + fun setCurrentPhase(httpConfig: String, phase: String) = launch({ val response = RetrofitServiceManager.setCurrentPhase(httpConfig, phase) - when (response.getResponseCode()) { - 200 -> { - loadState.value = LoadState.Success - setCurrentPhaseResult.value = true - } - - else -> { - loadState.value = LoadState.Fail - setCurrentPhaseResult.value = false - response.getResponseMessage().show(context) - } - } + setCurrentPhaseResult.value = response.getResponseCode() == 200 }, { - loadState.value = LoadState.Fail - it.printStackTrace() - }) - - fun uploadPhaseData( - context: Context, phase: String, imageList: ArrayList, base64List: ArrayList - ) = launch({ - loadState.value = LoadState.Loading - val response = RetrofitServiceManager.uploadPhaseData(phase, imageList, base64List) - when (response.getResponseCode()) { - 200 -> { - loadState.value = LoadState.Success - uploadDataResult.value = true - } - - else -> { - loadState.value = LoadState.Fail - uploadDataResult.value = false - response.getResponseMessage().show(context) - } - } - }, { - loadState.value = LoadState.Fail it.printStackTrace() }) } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4622ec3..3a86e57 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -58,6 +58,7 @@ + diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt index ad55f2b..0b16d05 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitService.kt @@ -66,15 +66,6 @@ suspend fun setCurrentPhase(@Body requestBody: RequestBody): String /** - * 提交场景下的数据 - */ - @POST("/prepare/upload") - suspend fun uploadPhaseData( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** * 声光报警开关 */ @POST("/setAlarmState") diff --git a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt index 938064e..dbaa1da 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/retrofit/RetrofitServiceManager.kt @@ -3,10 +3,8 @@ import android.util.Log import com.casic.br.operationsite.test.util.AuthenticationHelper import com.casic.br.operationsite.test.util.LocaleConstant -import com.casic.br.operationsite.test.util.RuntimeCache import com.google.gson.Gson import com.google.gson.JsonObject -import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.RetrofitFactory import com.pengxh.kt.lite.utils.SaveKeyValues @@ -83,29 +81,6 @@ } /** - * 提交场景下的数据 - */ - suspend fun uploadPhaseData( - phase: String, imageList: ArrayList, base64List: ArrayList - ): String { - val param = JsonObject() - param.addProperty("projectId", RuntimeCache.projectId) - param.addProperty("phase", phase) - - val typeToken = object : TypeToken>() {}.type - param.add( - "pathList", gson.toJsonTree(imageList, typeToken).asJsonArray - ) - param.add("base64List", gson.toJsonTree(base64List, typeToken).asJsonArray) - - val requestBody = param.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - - return api.uploadPhaseData(AuthenticationHelper.token!!, requestBody) - } - - /** * 设置当前阶段 */ suspend fun setCurrentPhase(httpConfig: String, phase: String): String { 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 new file mode 100644 index 0000000..e7b9477 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/service/UploadImageService.kt @@ -0,0 +1,68 @@ +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/util/HttpRequestHelper.kt b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt new file mode 100644 index 0000000..e522224 --- /dev/null +++ b/app/src/main/java/com/casic/br/operationsite/test/util/HttpRequestHelper.kt @@ -0,0 +1,132 @@ +package com.casic.br.operationsite.test.util + +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.lifecycleScope +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.pengxh.kt.lite.utils.Constant +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.logging.HttpLoggingInterceptor +import java.io.IOException +import java.util.concurrent.TimeUnit + +/** + * Service里面的Http请求 + * */ +class HttpRequestHelper(builder: Builder) : LifecycleOwner { + + private val kTag = "HttpRequestHelper" + private val registry = LifecycleRegistry(this) + private val gson by lazy { Gson() } + + class Builder { + lateinit var key: String + lateinit var value: String + lateinit var map: HashMap + lateinit var url: String + lateinit var httpRequestCallback: OnHttpRequestCallback + + /** + * 设置网络请求鉴权 + */ + fun setAuthentication(key: String = "token", value: String = ""): Builder { + this.key = key + this.value = value + return this + } + + /** + * 设置网络请求参数 + * */ + fun setRequestParam(map: HashMap): Builder { + this.map = map + return this + } + + /** + * 设置网络请求接口地址 + * */ + fun setRequestTarget(url: String): Builder { + this.url = url + return this + } + + /** + * 设置网络请求回调监听 + * */ + fun setOnHttpRequestCallback(httpRequestCallback: OnHttpRequestCallback): Builder { + this.httpRequestCallback = httpRequestCallback + return this + } + + fun build(): HttpRequestHelper { + return HttpRequestHelper(this) + } + } + + private val key = builder.key + private val value = builder.value + private val map = builder.map + private val url = builder.url + private val callback = builder.httpRequestCallback + + /** + * 发起网络请求 + * */ + fun start() { + val param = JsonObject() + map.forEach { + param.add(it.key, gson.toJsonTree(it.value)) + } + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + //构建Request + val request = Request.Builder().addHeader(key, value).post(requestBody).url(url).build() + lifecycleScope.launch(Dispatchers.IO) { + val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(interceptor) + .readTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(Constant.HTTP_TIMEOUT, TimeUnit.SECONDS) + .build() + try { + val response = client.newCall(request).execute() + response.body?.apply { + withContext(Dispatchers.Main) { + callback.onSuccess(string()) + } + } + } catch (e: IOException) { + withContext(Dispatchers.Main) { + callback.onFailure(e) + } + } + } + } + + interface OnHttpRequestCallback { + fun onSuccess(result: String) + + fun onFailure(throwable: Throwable) + } + + override fun getLifecycle(): Lifecycle { + return registry + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt index ba40569..34e438c 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/util/LocaleConstant.kt @@ -29,21 +29,22 @@ } const val SERVER_BASE_URL = "http://111.198.10.15:22006" + const val IMAGE_BED_URL = "${SERVER_BASE_URL}/emergency/prepareUpload" //一体机DeviceMonitor程序TCP Server IP地址 const val GAS_BASE_IP = "192.168.10.139" //一体机算法程序IP地址 - const val AI_BASE_IP = "192.168.10.139" + const val AI_BASE_IP = GAS_BASE_IP //相机IP const val CAMERA_IP = "192.168.10.137" //主码流 - const val MAIN_RTSP_URL = "rtsp://192.168.10.137:554" + const val MAIN_RTSP_URL = "rtsp://${CAMERA_IP}:554" //子码流 - const val SUB_RTSP_URL = "rtsp://192.168.10.137:554/h265/ch1/sub/av_stream" + const val SUB_RTSP_URL = "${MAIN_RTSP_URL}/h265/ch1/sub/av_stream" const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" const val DEVICE_CONTROL_SERVER_CONFIG = "deviceControlServerConfig" const val ACCOUNT = "account" 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 e970357..b607548 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 @@ -3,4 +3,7 @@ object RuntimeCache { var projectId = "" var userHelmetCode = "" + var uploadFileTaskId = "" + var imageArray = ArrayList>() + var imageId = "" } \ 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 9c774c7..24bef6b 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 @@ -25,8 +25,8 @@ import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.util.GlideLoadEngine import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.tcp.SocketManager -import com.casic.br.operationsite.test.vm.ConstructionCheckViewModel import com.casic.br.operationsite.test.vm.UploadFileViewModel import com.google.common.util.concurrent.ListenableFuture import com.luck.picture.lib.basic.PictureSelector @@ -52,6 +52,7 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale +import java.util.UUID import java.util.concurrent.ExecutionException import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -74,10 +75,10 @@ private lateinit var imageAnalysis: ImageAnalysis private lateinit var uploadFileViewModel: UploadFileViewModel private lateinit var imageAdapter: EditableImageAdapter - private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 private var isStart = false + private var index = 1 override fun initEvent() { binding.startCheckButton.setOnClickListener { @@ -151,7 +152,6 @@ } //发送指令 SocketManager.get.send(LocaleConstant.END_CONSTRUCTION_COMMAND) -// constructionCheckViewModel.uploadPhaseData(this, "brief", imagePaths, arrayListOf()) navigatePageTo() } } @@ -172,7 +172,7 @@ }, ContextCompat.getMainExecutor(this)) val viewWidth = getScreenWidth() - (15 + 15).dp2px(this) - imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 3, 3) + imageAdapter = EditableImageAdapter(this, recyclerViewImages, viewWidth, 2, 2) binding.recyclerView.addItemDecoration( RecyclerViewItemOffsets(marginOffset, marginOffset, marginOffset, marginOffset) ) @@ -183,21 +183,23 @@ if (it.code == 200) { val path = it.data.toString() if (path.isNotBlank()) { + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "brief" + map["image"] = path + map["index"] = index.toString() + map["base64"] = "" + RuntimeCache.imageArray.add(map) + index++ + val url = path.combineImagePath() - Log.d(kTag, "url: $url") imagePaths.add(path) recyclerViewImages.add(url) imageAdapter.notifyDataSetChanged() } } } - -// constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } } private fun bindPreview(cameraProvider: ProcessCameraProvider) { @@ -324,13 +326,6 @@ } } } - -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } } override fun setupTopBarLayout() { 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 af0849b..a9d448d 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 @@ -41,6 +41,7 @@ import java.util.Locale import java.util.Timer import java.util.TimerTask +import java.util.UUID import java.util.concurrent.TimeUnit @@ -49,7 +50,6 @@ private val kTag = "EnvironmentActivity" private val context = this private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val base64Array: ArrayList = ArrayList() private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var constructionCheckViewModel: ConstructionCheckViewModel private lateinit var workSiteViewModel: WorkSiteViewModel @@ -59,6 +59,7 @@ 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 { @@ -68,7 +69,19 @@ LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { try { val base64 = msg.obj as String - base64Array.add(base64) + + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "before_operation_environment" + map["image"] = "" + map["index"] = "1" + map["base64"] = base64 + if (!isDone) { + RuntimeCache.imageArray.add(map) + isDone = true + } + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) binding.blowerImageView.setImageBitmap(bitmap) @@ -92,7 +105,7 @@ } SocketManager.get.send(LocaleConstant.START_ENV_COMMAND) constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "before_operation_environment" + LocaleConstant.AI_BASE_IP, "before_operation_environment" ) } @@ -140,9 +153,6 @@ return@setOnClickListener } SocketManager.get.send(LocaleConstant.END_ENV_COMMAND) -// constructionCheckViewModel.uploadPhaseData( -// this, "before_operation_environment", arrayListOf(), base64Array -// ) navigatePageTo() } } @@ -152,11 +162,6 @@ weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// navigatePageTo() -// } -// } //动态设置rtspPlayerView宽高 val params = binding.rtspPlayerView.layoutParams as LinearLayout.LayoutParams @@ -166,8 +171,7 @@ params.height = videoHeight.toInt() binding.rtspPlayerView.layoutParams = params VideoPlayerManager.setGSYVideoPlayerOptions( - binding.rtspPlayerView, - LocaleConstant.SUB_RTSP_URL + binding.rtspPlayerView, LocaleConstant.SUB_RTSP_URL ) workSiteViewModel = ViewModelProvider(this)[WorkSiteViewModel::class.java] @@ -260,12 +264,7 @@ } override fun observeRequestState() { -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } + } override fun setupTopBarLayout() { 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 ba8427f..4df106e 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 @@ -58,18 +58,18 @@ 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 - private lateinit var timer: Timer - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val marginOffset by lazy { 1.dp2px(this) } - private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 override fun initEvent() { binding.alarmCheckbox.setOnCheckedChangeListener { _, isChecked -> @@ -167,9 +167,7 @@ } binding.startVideoCheckButton.setOnClickListener { - constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "in_operation" - ) + constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "in_operation") } binding.showControlViewButton.setOnClickListener { @@ -414,9 +412,8 @@ AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { isEndTask = true - constructionCheckViewModel.setCurrentPhase( - context, LocaleConstant.AI_BASE_IP, "stop" - ) + RuntimeCache.imageArray.clear() + constructionCheckViewModel.setCurrentPhase(LocaleConstant.AI_BASE_IP, "stop") } override fun onCancelClick() { 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 1156373..2fa7b4a 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 @@ -15,6 +15,7 @@ import com.casic.br.operationsite.test.databinding.ActivitySuppliesBinding import com.casic.br.operationsite.test.extensions.initImmersionBar import com.casic.br.operationsite.test.util.LocaleConstant +import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.util.VideoPlayerManager import com.casic.br.operationsite.test.util.tcp.SocketManager import com.casic.br.operationsite.test.vm.ConstructionCheckViewModel @@ -47,22 +48,23 @@ 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 { 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 imageAdapter: EditableImageAdapter private lateinit var timer: Timer private var webSocket: WebSocket? = null private var isWebSocketConnected = false - private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } - private val marginOffset by lazy { 1.dp2px(this) } - private val recyclerViewImages: ArrayList = ArrayList() //真实图片路径 - private val base64Array: ArrayList = ArrayList() + private var index = 1 override fun initEvent() { binding.startSuppliesCheckButton.setOnClickListener { @@ -74,7 +76,7 @@ SocketManager.get.send(LocaleConstant.START_SUPPLIES_COMMAND) delay(2000) constructionCheckViewModel.setCurrentPhase( - context, LocaleConstant.AI_BASE_IP, "before_operation_protection" + LocaleConstant.AI_BASE_IP, "before_operation_protection" ) withContext(Dispatchers.Main) { binding.stepView.text = "稍后开始检查第一项:四合一,请准备" @@ -86,10 +88,6 @@ BottomControlSheet(this).show() } -// binding.startVideoCheckButton.setOnClickListener { -// startVideoLauncher.launch(Intent(this, HelmetVideoActivity::class.java)) -// } - imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { "当前模式不支持手动添加图片".show(context) @@ -115,9 +113,6 @@ .setPositiveButton("确定").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { -// constructionCheckViewModel.uploadPhaseData( -// context, "before_operation_protection", arrayListOf(), base64Array -// ) SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) navigatePageTo() } @@ -133,9 +128,8 @@ private val startVideoLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { - Log.d(kTag, "startVideoLauncher: ") constructionCheckViewModel.setCurrentPhase( - this, LocaleConstant.AI_BASE_IP, "before_operation_protection" + LocaleConstant.AI_BASE_IP, "before_operation_protection" ) binding.stepView.text = "稍后开始检查第一项:四合一,请准备" } @@ -183,12 +177,6 @@ weakReferenceHandler = WeakReferenceHandler(this) constructionCheckViewModel = ViewModelProvider(this)[ConstructionCheckViewModel::class.java] -// constructionCheckViewModel.uploadDataResult.observe(this) { -// if (it) { -// SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) -// navigatePageTo() -// } -// } //动态设置rtspPlayerView宽高 val params = binding.rtspPlayerView.layoutParams as LinearLayout.LayoutParams @@ -226,7 +214,17 @@ LocaleConstant.WEBSOCKET_MESSAGE_CODE -> { try { val base64 = msg.obj as String - base64Array.add(base64) + + val map = HashMap() + map["id"] = RuntimeCache.uploadFileTaskId + map["imageId"] = UUID.randomUUID().toString() + map["scenario"] = "before_operation_protection" + map["image"] = "" + map["index"] = index.toString() + map["base64"] = base64 + RuntimeCache.imageArray.add(map) + index++ + val bitmapArray = Base64.decode(base64, Base64.DEFAULT) val bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.size) val imagePath = "/${createImageFileDir()}/IMG${timeFormat.format(Date())}.jpg" @@ -248,10 +246,6 @@ .setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { -// constructionCheckViewModel.uploadPhaseData( -// context, "before_operation_protection", -// arrayListOf(), base64Array -// ) SocketManager.get.send(LocaleConstant.START_VIDEO_COMMAND) navigatePageTo() } @@ -277,12 +271,7 @@ } override fun observeRequestState() { -// constructionCheckViewModel.loadState.observe(this) { -// when (it) { -// LoadState.Loading -> LoadingDialogHub.show(this, "数据提交中,请稍后...") -// else -> LoadingDialogHub.dismiss() -// } -// } + } override fun setupTopBarLayout() { 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 e848422..0721c79 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,6 +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.util.AuthenticationHelper import com.casic.br.operationsite.test.util.RuntimeCache import com.casic.br.operationsite.test.vm.LoginViewModel @@ -64,6 +65,7 @@ weakReferenceHandler = WeakReferenceHandler(this) startService(Intent(this, TcpMessageService::class.java)) + startService(Intent(this, UploadImageService::class.java)) workSiteViewModel = ViewModelProvider(this)[WorkSiteViewModel::class.java] getProjectListByPage() @@ -141,6 +143,7 @@ position: Int, t: WorkSiteListModel.DataModel.RowsModel ) { RuntimeCache.projectId = t.id + RuntimeCache.uploadFileTaskId = System.currentTimeMillis().toString() navigatePageTo() } }) diff --git a/app/src/main/java/com/casic/br/operationsite/test/vm/ConstructionCheckViewModel.kt b/app/src/main/java/com/casic/br/operationsite/test/vm/ConstructionCheckViewModel.kt index 760097e..e591d2e 100644 --- a/app/src/main/java/com/casic/br/operationsite/test/vm/ConstructionCheckViewModel.kt +++ b/app/src/main/java/com/casic/br/operationsite/test/vm/ConstructionCheckViewModel.kt @@ -1,20 +1,15 @@ package com.casic.br.operationsite.test.vm -import android.content.Context import androidx.lifecycle.MutableLiveData import com.casic.br.operationsite.test.extensions.getResponseCode -import com.casic.br.operationsite.test.extensions.getResponseMessage import com.casic.br.operationsite.test.retrofit.RetrofitServiceManager import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch -import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.LoadState class ConstructionCheckViewModel : BaseViewModel() { val setCurrentPhaseResult = MutableLiveData() val setVideoRegionResult = MutableLiveData() - val uploadDataResult = MutableLiveData() fun setVideoRegion(httpConfig: String, position: ArrayList) = launch({ val response = RetrofitServiceManager.setVideoRegion(httpConfig, position) @@ -23,45 +18,10 @@ it.printStackTrace() }) - fun setCurrentPhase(context: Context, httpConfig: String, phase: String) = launch({ - loadState.value = LoadState.Loading + fun setCurrentPhase(httpConfig: String, phase: String) = launch({ val response = RetrofitServiceManager.setCurrentPhase(httpConfig, phase) - when (response.getResponseCode()) { - 200 -> { - loadState.value = LoadState.Success - setCurrentPhaseResult.value = true - } - - else -> { - loadState.value = LoadState.Fail - setCurrentPhaseResult.value = false - response.getResponseMessage().show(context) - } - } + setCurrentPhaseResult.value = response.getResponseCode() == 200 }, { - loadState.value = LoadState.Fail - it.printStackTrace() - }) - - fun uploadPhaseData( - context: Context, phase: String, imageList: ArrayList, base64List: ArrayList - ) = launch({ - loadState.value = LoadState.Loading - val response = RetrofitServiceManager.uploadPhaseData(phase, imageList, base64List) - when (response.getResponseCode()) { - 200 -> { - loadState.value = LoadState.Success - uploadDataResult.value = true - } - - else -> { - loadState.value = LoadState.Fail - uploadDataResult.value = false - response.getResponseMessage().show(context) - } - } - }, { - loadState.value = LoadState.Fail it.printStackTrace() }) } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_disclosure.xml b/app/src/main/res/layout/activity_disclosure.xml index 9a438f8..5c7c3db 100644 --- a/app/src/main/res/layout/activity_disclosure.xml +++ b/app/src/main/res/layout/activity_disclosure.xml @@ -57,7 +57,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" - app:spanCount="3" /> + app:spanCount="2" />