diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + ().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + + android:orientation="vertical"> - + ().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + + android:orientation="vertical"> - + ().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + + android:orientation="vertical"> - + + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_navigation" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="设备详情" /> ().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + + android:orientation="vertical"> - + + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_navigation" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="设备详情" /> + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_show_right_image="true" /> ().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + + android:orientation="vertical"> - + + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_navigation" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="设备详情" /> + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_show_right_image="true" /> + android:orientation="vertical"> - ().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + + android:orientation="vertical"> - + + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_navigation" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="设备详情" /> + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_show_right_image="true" /> + android:orientation="vertical"> - + android:orientation="vertical"> ().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + + android:orientation="vertical"> - + + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_navigation" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="设备详情" /> + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_show_right_image="true" /> + android:orientation="vertical"> - + android:orientation="vertical"> - + ().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + + android:orientation="vertical"> - + + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_navigation" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="设备详情" /> + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_show_right_image="true" /> + android:orientation="vertical"> - + android:orientation="vertical"> - + @@ -22,7 +23,7 @@ android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" - android:text="@string/app_name" + android:text="手动选点" android:textColor="@color/white" android:textSize="@dimen/sp_18" /> diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + + android:orientation="vertical"> - + + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_navigation" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="设备详情" /> + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_show_right_image="true" /> + android:orientation="vertical"> - + android:orientation="vertical"> - + @@ -22,7 +23,7 @@ android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" - android:text="@string/app_name" + android:text="手动选点" android:textColor="@color/white" android:textSize="@dimen/sp_18" /> diff --git a/app/src/main/res/layout/dialog_progress.xml b/app/src/main/res/layout/dialog_progress.xml new file mode 100644 index 0000000..6c3f13d --- /dev/null +++ b/app/src/main/res/layout/dialog_progress.xml @@ -0,0 +1,31 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + + android:orientation="vertical"> - + + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_navigation" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="设备详情" /> + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_show_right_image="true" /> + android:orientation="vertical"> - + android:orientation="vertical"> - + @@ -22,7 +23,7 @@ android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" - android:text="@string/app_name" + android:text="手动选点" android:textColor="@color/white" android:textSize="@dimen/sp_18" /> diff --git a/app/src/main/res/layout/dialog_progress.xml b/app/src/main/res/layout/dialog_progress.xml new file mode 100644 index 0000000..6c3f13d --- /dev/null +++ b/app/src/main/res/layout/dialog_progress.xml @@ -0,0 +1,31 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml deleted file mode 100644 index daec7c8..0000000 --- a/app/src/main/res/layout/include_base_title.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index defbef7..12b867b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,10 +16,10 @@ defaultConfig { applicationId "com.casic.smarttube" - minSdkVersion 23 + minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "1.0.1" + versionCode 3 + versionName "1.0.2" } buildTypes { @@ -61,17 +61,15 @@ } dependencies { - //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1' + def base_version = "1.6.1" + implementation "androidx.appcompat:appcompat:${base_version}" + implementation "com.google.android.material:material:${base_version}" //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //沉浸式状态栏。基础依赖包,必须要依赖 implementation 'com.gyf.immersionbar:immersionbar:3.0.0' - //Loading框 - implementation 'com.github.ydstar:loadingdialog:1.0.0' //空白页 implementation 'com.qmuiteam:qmui:2.0.0-alpha10' implementation 'com.qmuiteam:arch:0.3.1' diff --git a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt index d39875e..d999103 100644 --- a/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt +++ b/app/src/main/java/com/casic/smarttube/adapter/DeviceListAdapter.kt @@ -32,9 +32,9 @@ private var deleteAction = QMUISwipeAction.ActionBuilder() .icon(ContextCompat.getDrawable(context, R.drawable.ic_delete_white)) - .textSize(16f.dp2px(context)) + .textSize(16.dp2px(context)) .textColor(Color.WHITE) - .paddingStartEnd(16f.dp2px(context)).text("删除") + .paddingStartEnd(16.dp2px(context)).text("删除") .backgroundColor(Color.RED) .build() diff --git a/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt new file mode 100644 index 0000000..df02ad7 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/extensions/ViewGroup.kt @@ -0,0 +1,19 @@ +package com.casic.smarttube.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt index a39c096..0cb450f 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/HomePageFragment.kt @@ -41,8 +41,8 @@ import com.pengxh.kt.lite.base.KotlinBaseFragment import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet @@ -54,8 +54,8 @@ private val kTag = "HomePageFragment" private val geocoderSearch by lazy { GeocodeSearch(requireContext()) } + private val easyPopupWindow by lazy { EasyPopupWindow(requireContext()) } private lateinit var weakReferenceHandler: WeakReferenceHandler - private lateinit var easyPopupWindow: EasyPopupWindow private lateinit var aMap: AMap private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel @@ -111,8 +111,26 @@ override fun initOnCreate(savedInstanceState: Bundle?) { weakReferenceHandler = WeakReferenceHandler(this) - easyPopupWindow = EasyPopupWindow(requireContext()) - easyPopupWindow.setPopupMenuItem(LocaleConstant.POPUP_IMAGES, LocaleConstant.POPUP_TITLES) + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL + 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE + } + } + }) //初始化vm deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] @@ -205,17 +223,8 @@ override fun initEvent() { binding.rightOptionView.setOnClickListener { - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> aMap.mapType = AMap.MAP_TYPE_NORMAL - 1 -> aMap.mapType = AMap.MAP_TYPE_SATELLITE - } - } - }) easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width + val x = binding.rightOptionView.width - easyPopupWindow.width easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) } diff --git a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt index cc35197..f20cb4e 100644 --- a/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt +++ b/app/src/main/java/com/casic/smarttube/fragment/MinePageFragment.kt @@ -1,9 +1,6 @@ package com.casic.smarttube.fragment -import android.app.ProgressDialog import android.content.Intent -import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.CountDownTimer import android.view.LayoutInflater @@ -11,11 +8,10 @@ import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import com.casic.smarttube.BuildConfig -import com.casic.smarttube.R import com.casic.smarttube.databinding.FragmentMineBinding -import com.casic.smarttube.extensions.appendDownloadUrl import com.casic.smarttube.model.UserDetailModel import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.FileDownloadManager import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.LocaleConstant import com.casic.smarttube.utils.RSAUtils @@ -24,20 +20,19 @@ import com.casic.smarttube.vm.LoginViewModel import com.casic.smarttube.vm.UserViewModel import com.casic.smarttube.vm.VersionViewModel +import com.casic.smarttube.widgets.ProgressDialog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.base.KotlinBaseFragment -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.calculateSize import com.pengxh.kt.lite.extensions.createDownloadFileDir import com.pengxh.kt.lite.extensions.deleteFile -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.formatFileSize import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.PageNavigationManager +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog import java.io.File @@ -50,7 +45,6 @@ private lateinit var userViewModel: UserViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var versionViewModel: VersionViewModel - private lateinit var progressDialog: ProgressDialog override fun initViewBinding( inflater: LayoutInflater, container: ViewGroup? @@ -66,13 +60,6 @@ userViewModel = ViewModelProvider(this)[UserViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java] - - //初始化下载对话框 - progressDialog = ProgressDialog(requireContext()) - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) - progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress)) - progressDialog.setCanceledOnTouchOutside(false) - progressDialog.setCancelable(false) } override fun observeRequestState() { @@ -84,7 +71,7 @@ LoadingDialogHub.dismiss() AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } else -> LoadingDialogHub.dismiss() @@ -209,7 +196,7 @@ if (it.code == 200) { AuthenticationHelper.removeToken() requireContext().navigatePageTo() - PageNavigationManager.finishAllActivity() + ActivityStackManager.finishAllActivity() } } } @@ -246,54 +233,43 @@ binding.userDeptView.text = String.format("部门:${userData.deptName}") } - private fun downloadApk(url: String?) { - progressDialog.setMessage("下载新版本中...") + private fun downloadApk(url: String) { + val progressDialog = ProgressDialog(requireContext()) progressDialog.show() - if (url.toString().isBlank()) { - "抱歉,版本下载失败".show(requireContext()) - return - } - /** - * http://111.198.10.15:11304/static/apk/1.0.1.apk - * */ - val downloadPath = url!!.appendDownloadUrl() - //开始下载 - downloadPath.downloadFile( - requireContext().createDownloadFileDir().toString(), - object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() + FileDownloadManager.Builder() + .setDownloadFileSource(url) + .setFileSuffix("apk") + .setFileSaveDirectory(requireContext().createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadStart(total: Long) { + progressDialog.setMaxProgress(total) } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } - - override fun onDownloadEnd(file: File?) { + override fun onDownloadEnd(file: File) { progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK + //安装APK文件 installApk(file) } - }) + + override fun onFailed(t: Throwable) { + t.printStackTrace() + progressDialog.dismiss() + } + + override fun onProgressChanged(progress: Long) { + progressDialog.updateProgress(progress) + } + }).build().start() } - private fun installApk(apkPackage: File?) { - if (apkPackage == null) { - "文件异常,无法安装".show(requireContext()) - return + private fun installApk(file: File) { + val apkUri = FileProvider.getUriForFile( + requireContext(), "${requireContext().packageName}.provider", file + ) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(apkUri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) } - val intent = Intent(Intent.ACTION_VIEW) - val data: Uri - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0 - data = FileProvider.getUriForFile( - requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage - ) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权 - } else { - data = Uri.fromFile(apkPackage) - } - intent.setDataAndType(data, "application/vnd.android.package-archive") requireContext().startActivity(intent) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt new file mode 100644 index 0000000..e13a15a --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitService.kt @@ -0,0 +1,212 @@ +package com.casic.smarttube.retrofit + +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.* + + +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): String + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 退出登录 + */ + @GET("/user/logout") + suspend fun loginOut(@Header("token") token: String): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 修改密码 + * + * @param oldPwd 旧密码 + * @param newPwd 新密码 + */ + @FormUrlEncoded + @POST("/mgr/changePwd") + suspend fun changePassword( + @Header("token") token: String, + @Field("oldPwd") oldPwd: String, + @Field("newPwd") newPwd: String + ): String + + /** + * 上传图片 + * 系统路径static拼接图片返回路径 + * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg + */ + @Multipart + @POST("/imageUpload") + suspend fun uploadImage( + @Header("token") token: String, + @Part file: MultipartBody.Part + ): String + + /** + * 更新APK版本 + */ + @POST("/app/checkVersion") + suspend fun obtainVersionResult(@Header("token") token: String): String + + /** + * 地图设备列表 + */ + @GET("/tube/well/list") + suspend fun obtainMapDeviceList(@Header("token") token: String): String + + /** + * 项目列表 + */ + @GET("/tube/groups/list") + suspend fun obtainProGroupList(@Header("token") token: String): String + + /** + * 根据项目ID查询该项目下的设备列表 + */ + @GET("/tube/groupdevice/list") + suspend fun obtainDeviceListByGroup( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String + ): String + + /** + * 获取设备分页列表 + * */ + @GET("/tube/groupdevice/listpage") + suspend fun obtainDeviceListByPage( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String?, + @Query("order") order: Int, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取设备详情 + * + * @param wellGroupId 组 + * @param devcode 管盯设备编号 + */ + @GET("/tube/detail") + suspend fun obtainDeviceDetail( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 根据部门获取区ID + * + * @param deptId + */ + @GET("/config/getAreaByDept") + suspend fun obtainAreaByDept( + @Header("token") token: String, + @Query("deptId") deptId: String + ): String + + /** + * 获取区/县等 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainDistrict( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取街道 + * + * @param pid + */ + @GET("/area/list") + suspend fun obtainStreet( + @Header("token") token: String, + @Query("pid") pid: String + ): String + + /** + * 获取管盯历史数据 + * */ + @GET("/tube/groupdevice/history") + suspend fun obtainDeviceHistoryData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String?, + @Query("beginTime") beginTime: String?, + @Query("endTime") endTime: String? + ): String + + /** + * 获取设备最新数据 + * + * @param wellGroupId 管盯设备编号 + */ + @GET("/tube/latestdata") + suspend fun obtainTubeLastData( + @Header("token") token: String, + @Query("wellGroupId") wellGroupId: String, + @Query("devcode") devcode: String + ): String + + /** + * 查询工单 + * */ + @POST("/tube/qrcode-entry/add") + suspend fun addDevice( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String + + /** + * 获取项目编号列表 + */ + @GET("/tube/groupdict") + suspend fun obtainGroupList( + @Header("token") token: String + ): String + + /** + * 修改项目编号 + */ + @GET("/tube/group/edit") + suspend fun changeGroupId( + @Header("token") token: String, + @Query("oldGroupName") oldGroupId: String, + @Query("newGroupName") newGroupId: String + ): String + + /** + * 删除设备 + * */ + @POST("/tube/batch/delete") + suspend fun deleteDeviceById( + @Header("token") token: String, + @Body requestBody: RequestBody + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..132c9d4 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,210 @@ +package com.casic.smarttube.retrofit + +import com.casic.smarttube.utils.AuthenticationHelper +import com.casic.smarttube.utils.LocaleConstant +import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit +import com.pengxh.kt.lite.utils.SaveKeyValues +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import java.io.File + + +object RetrofitServiceManager { + + private val api by lazy { + val httpConfig = SaveKeyValues.getValue( + LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL + ) as String + createRetrofit(httpConfig) + } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): String { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 退出登录 + */ + suspend fun loginOut(): String { + return api.loginOut(AuthenticationHelper.token!!) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 修改密码 + */ + suspend fun changePassword(oldPwd: String, newPwd: String): String { + return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) + } + + /** + * 更新APK版本 + */ + suspend fun updateVersion(): String { + return api.obtainVersionResult(AuthenticationHelper.token!!) + } + + /** + * 地图设备列表 + */ + suspend fun obtainMapDeviceList(): String { + return api.obtainMapDeviceList(AuthenticationHelper.token!!) + } + + /** + * 项目列表 + */ + suspend fun obtainProGroupList(): String { + return api.obtainProGroupList(AuthenticationHelper.token!!) + } + + /** + * 根据项目ID查询该项目下的设备列表 + */ + suspend fun obtainDeviceListByGroup(wellGroupId: String): String { + return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) + } + + /** + * 获取设备分页列表 + */ + suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { + return api.obtainDeviceListByPage( + AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT + ) + } + + /** + * 获取设备详情 + */ + suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { + return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) + } + + /** + * 根据部门获取区ID + */ + suspend fun obtainAreaByDept(deptId: String): String { + return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) + } + + /** + * 获取区/县等 + */ + suspend fun obtainDistrict(pid: String): String { + return api.obtainDistrict(AuthenticationHelper.token!!, pid) + } + + /** + * 获取街道 + */ + suspend fun obtainStreet(pid: String): String { + return api.obtainStreet(AuthenticationHelper.token!!, pid) + } + + /** + * 根据设备编号获取历史数据 + */ + suspend fun obtainDeviceHistoryData( + groupId: String, devcode: String, beginTime: String?, endTime: String? + ): String { + return api.obtainDeviceHistoryData( + AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime + ) + } + + /** + * 上传图片 + */ + suspend fun uploadImage(image: File): String { + val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) + val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) + return api.uploadImage(AuthenticationHelper.token!!, imagePart) + } + + /** + * 获取设备最新数据 + */ + suspend fun obtainTubeLastData(groupId: String, devcode: String): String { + return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) + } + + /** + * 添加设备 + */ + suspend fun addDevice( + deviceCode: String, + deviceName: String, + ownerShip: String, + interval: String, + longitude: String, + latitude: String, + imagePaths: String, + scene: String, + addDeviceTime: String, + userId: String, + deptId: String + ): String { + val paramObject = JSONObject() + paramObject.put("deviceCode", deviceCode) + paramObject.put("deviceName", deviceName) + paramObject.put("projectName", ownerShip) + paramObject.put("frequency", interval) + paramObject.put("lng", longitude) + paramObject.put("lat", latitude) + paramObject.put("image", imagePaths) + paramObject.put("description", scene) + paramObject.put("createTime", addDeviceTime) + paramObject.put("ownerId", userId) + paramObject.put("deptId", deptId) + paramObject.put("version", "19") + val requestBody = paramObject.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.addDevice(AuthenticationHelper.token!!, requestBody) + } + + /** + * 获取项目编号列表 + */ + suspend fun obtainGroupList(): String { + return api.obtainGroupList(AuthenticationHelper.token!!) + } + + /** + * 修改项目编号 + */ + suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { + return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) + } + + /** + * 删除设备 + */ + suspend fun deleteDeviceById(ids: List): String { + val requestBody = ids.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt new file mode 100644 index 0000000..46f4aa5 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/utils/FileDownloadManager.kt @@ -0,0 +1,150 @@ +package com.casic.smarttube.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Call +import okhttp3.Callback +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import java.io.File +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean + +class FileDownloadManager(builder: Builder) { + + private val httpClient by lazy { OkHttpClient() } + + class Builder { + lateinit var url: String + lateinit var suffix: String + lateinit var directory: File + lateinit var downloadListener: OnFileDownloadListener + + /** + * 文件下载地址 + * */ + fun setDownloadFileSource(url: String): Builder { + this.url = url + return this + } + + /** + * 文件后缀 + * 如:apk等 + * */ + fun setFileSuffix(suffix: String): Builder { + this.suffix = if (suffix.contains(".")) { + //去掉前缀的点 + suffix.drop(1) + } else { + suffix + } + return this + } + + /** + * 文件保存的地址 + * */ + fun setFileSaveDirectory(directory: File): Builder { + this.directory = directory + return this + } + + /** + * 设置文件下载回调监听 + * */ + fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder { + this.downloadListener = downloadListener + return this + } + + fun build(): FileDownloadManager { + if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) { + throw IllegalStateException("All properties must be initialized before building.") + } + return FileDownloadManager(this) + } + } + + private val url = builder.url + private val suffix = builder.suffix + private val directory = builder.directory + private val listener = builder.downloadListener + + /** + * 开始下载 + * */ + fun start() { + val job = SupervisorJob() + val scope = CoroutineScope(Dispatchers.Main + job) + + val request = Request.Builder().get().url(url).build() + val newCall = httpClient.newCall(request) + val isExecuting = AtomicBoolean(false) + + /** + * 如果已被加入下载队列,则取消之前的,重新下载 + */ + if (isExecuting.getAndSet(true)) { + newCall.cancel() + } + + //异步下载文件 + newCall.enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + scope.launch(Dispatchers.Main) { + listener.onFailed(e) + } + } + + override fun onResponse(call: Call, response: Response) { + scope.launch(Dispatchers.IO) { + val body = response.body + if (body == null) { + listener.onFailed(IOException("Response body is null")) + throw IOException("Response body is null") + } else { + val inputStream = body.byteStream() + val fileSize = body.contentLength() + + if (fileSize <= 0) { + throw IllegalArgumentException("Invalid file size") + } + listener.onDownloadStart(fileSize) + + val file = File(directory, "${System.currentTimeMillis()}.${suffix}") + file.outputStream().use { fos -> + val buffer = ByteArray(2048) + var sum = 0L + var read: Int + while (inputStream.read(buffer).also { read = it } != -1) { + fos.write(buffer, 0, read) + sum += read.toLong() + withContext(Dispatchers.Main) { + listener.onProgressChanged(sum) + } + } + } + + withContext(Dispatchers.Main) { + listener.onDownloadEnd(file) + } + + job.cancel() + } + } + } + }) + } + + interface OnFileDownloadListener { + fun onDownloadStart(total: Long) + fun onProgressChanged(progress: Long) + fun onDownloadEnd(file: File) + fun onFailed(t: Throwable) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt deleted file mode 100644 index 4034111..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitService.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import okhttp3.MultipartBody -import okhttp3.RequestBody -import retrofit2.http.* - - -interface RetrofitService { - /** - * PublicKey校验 - */ - @GET("/config/baseConfig") - suspend fun obtainPublicKey(): String - - /** - * 登录并获取Token - * - * @param sid - * @param account 用户名 - * @param secretKey 加密后的密码 - */ - @FormUrlEncoded - @POST("/user/login") - suspend fun obtainLoginResult( - @Field("sid") sid: String, - @Field("username") account: String, - @Field("password") secretKey: String - ): String - - /** - * 退出登录 - */ - @GET("/user/logout") - suspend fun loginOut(@Header("token") token: String): String - - /** - * 获取用户信息 - */ - @GET("/user/info") - suspend fun obtainUserDetail(@Header("token") token: String): String - - /** - * 修改密码 - * - * @param oldPwd 旧密码 - * @param newPwd 新密码 - */ - @FormUrlEncoded - @POST("/mgr/changePwd") - suspend fun changePassword( - @Header("token") token: String, - @Field("oldPwd") oldPwd: String, - @Field("newPwd") newPwd: String - ): String - - /** - * 上传图片 - * 系统路径static拼接图片返回路径 - * http://xx.com/static/2019-10/8050891248624f2bbefedcb196ce89cb.jpeg - */ - @Multipart - @POST("/imageUpload") - suspend fun uploadImage( - @Header("token") token: String, - @Part file: MultipartBody.Part - ): String - - /** - * 更新APK版本 - */ - @POST("/app/checkVersion") - suspend fun obtainVersionResult(@Header("token") token: String): String - - /** - * 地图设备列表 - */ - @GET("/tube/well/list") - suspend fun obtainMapDeviceList(@Header("token") token: String): String - - /** - * 项目列表 - */ - @GET("/tube/groups/list") - suspend fun obtainProGroupList(@Header("token") token: String): String - - /** - * 根据项目ID查询该项目下的设备列表 - */ - @GET("/tube/groupdevice/list") - suspend fun obtainDeviceListByGroup( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String - ): String - - /** - * 获取设备分页列表 - * */ - @GET("/tube/groupdevice/listpage") - suspend fun obtainDeviceListByPage( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String?, - @Query("order") order: Int, - @Query("offset") offset: Int, - @Query("limit") limit: Int - ): String - - /** - * 获取设备详情 - * - * @param wellGroupId 组 - * @param devcode 管盯设备编号 - */ - @GET("/tube/detail") - suspend fun obtainDeviceDetail( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 根据部门获取区ID - * - * @param deptId - */ - @GET("/config/getAreaByDept") - suspend fun obtainAreaByDept( - @Header("token") token: String, - @Query("deptId") deptId: String - ): String - - /** - * 获取区/县等 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainDistrict( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取街道 - * - * @param pid - */ - @GET("/area/list") - suspend fun obtainStreet( - @Header("token") token: String, - @Query("pid") pid: String - ): String - - /** - * 获取管盯历史数据 - * */ - @GET("/tube/groupdevice/history") - suspend fun obtainDeviceHistoryData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String?, - @Query("beginTime") beginTime: String?, - @Query("endTime") endTime: String? - ): String - - /** - * 获取设备最新数据 - * - * @param wellGroupId 管盯设备编号 - */ - @GET("/tube/latestdata") - suspend fun obtainTubeLastData( - @Header("token") token: String, - @Query("wellGroupId") wellGroupId: String, - @Query("devcode") devcode: String - ): String - - /** - * 查询工单 - * */ - @POST("/tube/qrcode-entry/add") - suspend fun addDevice( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String - - /** - * 获取项目编号列表 - */ - @GET("/tube/groupdict") - suspend fun obtainGroupList( - @Header("token") token: String - ): String - - /** - * 修改项目编号 - */ - @GET("/tube/group/edit") - suspend fun changeGroupId( - @Header("token") token: String, - @Query("oldGroupName") oldGroupId: String, - @Query("newGroupName") newGroupId: String - ): String - - /** - * 删除设备 - * */ - @POST("/tube/batch/delete") - suspend fun deleteDeviceById( - @Header("token") token: String, - @Body requestBody: RequestBody - ): String -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt deleted file mode 100644 index b8d3c92..0000000 --- a/app/src/main/java/com/casic/smarttube/utils/retrofit/RetrofitServiceManager.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.casic.smarttube.utils.retrofit - -import com.casic.smarttube.utils.AuthenticationHelper -import com.casic.smarttube.utils.LocaleConstant -import com.pengxh.kt.lite.utils.RetrofitFactory.createRetrofit -import com.pengxh.kt.lite.utils.SaveKeyValues -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import org.json.JSONObject -import java.io.File - - -object RetrofitServiceManager { - - private val api by lazy { - val httpConfig = SaveKeyValues.getValue( - LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.SERVER_BASE_URL - ) as String - createRetrofit(httpConfig) - } - - /** - * 验证PublicKey - */ - suspend fun authenticate(): String { - return api.obtainPublicKey() - } - - /** - * 登录并获取Token - */ - suspend fun login(sid: String, account: String, secretKey: String): String { - return api.obtainLoginResult(sid, account, secretKey) - } - - /** - * 退出登录 - */ - suspend fun loginOut(): String { - return api.loginOut(AuthenticationHelper.token!!) - } - - /** - * 获取用户信息 - */ - suspend fun obtainUserDetail(): String { - return api.obtainUserDetail(AuthenticationHelper.token!!) - } - - /** - * 修改密码 - */ - suspend fun changePassword(oldPwd: String, newPwd: String): String { - return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd) - } - - /** - * 更新APK版本 - */ - suspend fun updateVersion(): String { - return api.obtainVersionResult(AuthenticationHelper.token!!) - } - - /** - * 地图设备列表 - */ - suspend fun obtainMapDeviceList(): String { - return api.obtainMapDeviceList(AuthenticationHelper.token!!) - } - - /** - * 项目列表 - */ - suspend fun obtainProGroupList(): String { - return api.obtainProGroupList(AuthenticationHelper.token!!) - } - - /** - * 根据项目ID查询该项目下的设备列表 - */ - suspend fun obtainDeviceListByGroup(wellGroupId: String): String { - return api.obtainDeviceListByGroup(AuthenticationHelper.token!!, wellGroupId) - } - - /** - * 获取设备分页列表 - */ - suspend fun obtainDeviceListByPage(groupId: String, order: Int, page: Int): String { - return api.obtainDeviceListByPage( - AuthenticationHelper.token!!, groupId, order, page, LocaleConstant.PAGE_LIMIT - ) - } - - /** - * 获取设备详情 - */ - suspend fun obtainDeviceDetail(groupId: String, tubeId: String): String { - return api.obtainDeviceDetail(AuthenticationHelper.token!!, groupId, tubeId) - } - - /** - * 根据部门获取区ID - */ - suspend fun obtainAreaByDept(deptId: String): String { - return api.obtainAreaByDept(AuthenticationHelper.token!!, deptId) - } - - /** - * 获取区/县等 - */ - suspend fun obtainDistrict(pid: String): String { - return api.obtainDistrict(AuthenticationHelper.token!!, pid) - } - - /** - * 获取街道 - */ - suspend fun obtainStreet(pid: String): String { - return api.obtainStreet(AuthenticationHelper.token!!, pid) - } - - /** - * 根据设备编号获取历史数据 - */ - suspend fun obtainDeviceHistoryData( - groupId: String, devcode: String, beginTime: String?, endTime: String? - ): String { - return api.obtainDeviceHistoryData( - AuthenticationHelper.token!!, groupId, devcode, beginTime, endTime - ) - } - - /** - * 上传图片 - */ - suspend fun uploadImage(image: File): String { - val requestBody = RequestBody.create("image/png".toMediaTypeOrNull(), image) - val imagePart = MultipartBody.Part.createFormData("file", image.name, requestBody) - return api.uploadImage(AuthenticationHelper.token!!, imagePart) - } - - /** - * 获取设备最新数据 - */ - suspend fun obtainTubeLastData(groupId: String, devcode: String): String { - return api.obtainTubeLastData(AuthenticationHelper.token!!, groupId, devcode) - } - - /** - * 添加设备 - */ - suspend fun addDevice( - deviceCode: String, - deviceName: String, - ownerShip: String, - interval: String, - longitude: String, - latitude: String, - imagePaths: String, - scene: String, - addDeviceTime: String, - userId: String, - deptId: String - ): String { - val paramObject = JSONObject() - paramObject.put("deviceCode", deviceCode) - paramObject.put("deviceName", deviceName) - paramObject.put("projectName", ownerShip) - paramObject.put("frequency", interval) - paramObject.put("lng", longitude) - paramObject.put("lat", latitude) - paramObject.put("image", imagePaths) - paramObject.put("description", scene) - paramObject.put("createTime", addDeviceTime) - paramObject.put("ownerId", userId) - paramObject.put("deptId", deptId) - paramObject.put("version", "19") - val requestBody = paramObject.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.addDevice(AuthenticationHelper.token!!, requestBody) - } - - /** - * 获取项目编号列表 - */ - suspend fun obtainGroupList(): String { - return api.obtainGroupList(AuthenticationHelper.token!!) - } - - /** - * 修改项目编号 - */ - suspend fun changeGroupId(oldGroupId: String, newGroupId: String): String { - return api.changeGroupId(AuthenticationHelper.token!!, oldGroupId, newGroupId) - } - - /** - * 删除设备 - */ - suspend fun deleteDeviceById(ids: List): String { - val requestBody = ids.toString().toRequestBody( - "application/json;charset=UTF-8".toMediaType() - ) - return api.deleteDeviceById(AuthenticationHelper.token!!, requestBody) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt index 598581a..b977427 100644 --- a/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AboutUsActivity.kt @@ -4,10 +4,9 @@ import com.casic.smarttube.BuildConfig import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityAboutUsBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.widget.TitleBarView class AboutUsActivity : KotlinBaseActivity() { @@ -16,10 +15,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "关于我们" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt index 80b83bd..e523b36 100644 --- a/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/AddDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -19,6 +18,7 @@ import com.casic.smarttube.databinding.ActivityAddDeviceBinding import com.casic.smarttube.extensions.combineImagePath import com.casic.smarttube.extensions.compressImage +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.isNumber import com.casic.smarttube.extensions.reformat import com.casic.smarttube.model.UserDetailModel @@ -32,7 +32,6 @@ import com.casic.smarttube.vm.UploadImageViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -43,10 +42,10 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.timestampToCompleteDate -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertInputDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import java.io.File @@ -59,7 +58,7 @@ private lateinit var uploadImageViewModel: UploadImageViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var groupViewModel: ProjectGroupViewModel - private val context: Context = this@AddDeviceActivity + private val context = this private val imagePaths: ArrayList = ArrayList() //服务器返回的拍照数据集 private val realPaths: ArrayList = ArrayList() //真实图片路径 private val frequency = listOf("1min", "2min", "5min", "10min", "15min", "30min", "60min") @@ -78,10 +77,16 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "添加设备" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -222,7 +227,7 @@ }).build().show() } - imageAdapter = EditableImageAdapter(this, 3, 13f) +// imageAdapter = EditableImageAdapter(this, 3, 13f) binding.addImageRecyclerView.adapter = imageAdapter imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener { override fun onAddImageClick() { @@ -239,7 +244,7 @@ override fun onItemLongClick(view: View?, position: Int) { imagePaths.removeAt(position) - imageAdapter.deleteImage(position) +// imageAdapter.deleteImage(position) } }) @@ -254,7 +259,7 @@ imagePaths.add(url) realPaths.add(url.combineImagePath()) } - imageAdapter.setupImage(realPaths) +// imageAdapter.setupImage(realPaths) } else { "最多只能上传3张图片".show(this) } diff --git a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt index e4f19a4..4a7e884 100644 --- a/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/BigImageActivity.kt @@ -6,19 +6,16 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.bumptech.glide.Glide import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityBigImageBinding -import com.gyf.immersionbar.ImmersionBar +import com.casic.smarttube.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.utils.PageNavigationManager - +import com.pengxh.kt.lite.utils.ActivityStackManager +import com.pengxh.kt.lite.utils.LiteKitConstant class BigImageActivity : KotlinBaseActivity() { @@ -27,14 +24,13 @@ } override fun setupTopBarLayout() { - PageNavigationManager.addActivity(this) - ImmerseStatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.black)) - ImmersionBar.with(this).statusBarDarkFont(false).init() + ActivityStackManager.addActivity(this) + binding.rootView.initImmersionBar(this, true, R.color.black) } override fun initOnCreate(savedInstanceState: Bundle?) { - val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) - val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) + val index = intent.getIntExtra(LiteKitConstant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val urls = intent.getStringArrayListExtra(LiteKitConstant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return } @@ -69,7 +65,7 @@ binding.leftBackView.setOnClickListener { this.finish() } } - class BigImageAdapter(private var context: Context, imageList: ArrayList) : + inner class BigImageAdapter(private var context: Context, imageList: ArrayList) : PagerAdapter() { private var images: ArrayList = imageList @@ -80,18 +76,14 @@ override fun instantiateItem(container: ViewGroup, position: Int): Any { val view = LayoutInflater.from(context).inflate( - R.layout.item_big_picture, - container, - false + R.layout.item_big_picture, container, false ) val photoView: PhotoView = view.findViewById(R.id.photoView) Glide.with(context).load(images[position]).into(photoView) photoView.scaleType = ImageView.ScaleType.CENTER_INSIDE container.addView(view) //点击大图取消预览 - photoView.setOnClickListener { - PageNavigationManager.currentActivity().finish() - } + photoView.setOnClickListener { finish() } return view } diff --git a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt index f036a78..2e490c3 100644 --- a/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/DeviceDetailActivity.kt @@ -13,24 +13,24 @@ import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityDeviceDetailBinding import com.casic.smarttube.extensions.combineImagePath +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.toSignalImage import com.casic.smarttube.model.DeviceDetailModel import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.adapter.ReadOnlyImageAdapter import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class DeviceDetailActivity : KotlinBaseActivity() { private val kTag = "DeviceDetailActivity" + private val context = this private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceModel: DeviceDetailModel.DataModel private val geocoderSearch by lazy { GeocodeSearch(this) } @@ -40,14 +40,26 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleView.text = "设备详情" - binding.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + val lat = deviceModel.latGaode.toString() + val lng = deviceModel.lngGaode.toString() + if (lat.isBlank() || lng.isBlank()) { + "经纬度异常,无法开启导航".show(context) + return + } + RouteOnMap.startNavigation(context, "", LatLng(lat.toDouble(), lng.toDouble())) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] deviceViewModel.obtainDeviceDetail(params[0], params[1]) @@ -138,14 +150,6 @@ } override fun initEvent() { - binding.rightOptionView.setOnClickListener { - val lat = deviceModel.latGaode.toString() - val lng = deviceModel.lngGaode.toString() - if (lat.isBlank() || lng.isBlank()) { - "经纬度异常,无法开启导航".show(this) - return@setOnClickListener - } - RouteOnMap.startNavigation(this, "", LatLng(lat.toDouble(), lng.toDouble())) - } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt index ba52ab8..b393c0b 100644 --- a/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/GroupDeviceActivity.kt @@ -1,6 +1,5 @@ package com.casic.smarttube.view -import android.content.Context import android.os.Bundle import android.os.Handler import android.view.ViewGroup @@ -10,6 +9,7 @@ import com.casic.smarttube.R import com.casic.smarttube.adapter.DeviceListAdapter import com.casic.smarttube.databinding.ActivityGroupDeviceBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.extensions.showEmptyPage import com.casic.smarttube.model.DeviceListModel import com.casic.smarttube.utils.LoadingDialogHub @@ -17,16 +17,14 @@ import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.vm.ProjectGroupViewModel import com.casic.smarttube.widgets.MultiSelectDialog -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.EasyPopupWindow +import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction import com.qmuiteam.qmui.recyclerView.QMUISwipeAction @@ -38,7 +36,8 @@ private lateinit var groupViewModel: ProjectGroupViewModel private lateinit var deviceViewModel: DeviceViewModel private lateinit var deviceAdapter: DeviceListAdapter - private val context: Context = this@GroupDeviceActivity + private val context = this + private val easyPopupWindow by lazy { EasyPopupWindow(this) } private var dataBeans: MutableList = ArrayList() private var pageIndex = 1 private var isRefresh = false @@ -52,91 +51,106 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.leftBackView.setOnClickListener { finish() } - binding.rightOptionView.setOnClickListener { - //改为Popup - val easyPopupWindow = EasyPopupWindow(this) - easyPopupWindow.setPopupMenuItem( - LocaleConstant.DEVICE_OPERATE_IMAGES, LocaleConstant.DEVICE_OPERATE_TITLES - ) - easyPopupWindow.setOnPopupWindowClickListener(object : - EasyPopupWindow.OnPopupWindowClickListener { - override fun onPopupItemClicked(position: Int) { - when (position) { - 0 -> { - order = if (order == 0) { - 1 - } else { - 0 - } - pageIndex = 1 - obtainDeviceListByPage() - } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } - 1 -> { - AlertControlDialog.Builder().setContext(context).setTitle("提示") - .setMessage("删除后将无法恢复,是否继续?") - .setNegativeButton("容我想想").setPositiveButton("已经想好") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onCancelClick() { - - } - - override fun onConfirmClick() { - val ids = ArrayList() - dataBeans.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - - } - }).build().show() - } - - 2 -> { - MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) - .setTitle("选择设备").setDataSource(dataBeans) - .setNegativeButton("取消").setPositiveButton("选好了") - .setOnDialogButtonClickListener(object : - MultiSelectDialog.OnDialogButtonClickListener { - override fun onConfirmClick(selectedModels: MutableList) { - val ids = ArrayList() - selectedModels.forEach { - if (!it.deviceId.isNullOrBlank()) { - ids.add(it.deviceId.toLong()) - } - } - isDeleteAll = true - deviceViewModel.deleteDeviceById(ids) - } - - override fun onCancelClick() { - - } - }).build().show() - } - } - } - }) - easyPopupWindow.setBackgroundDrawable(null) - val x: Int = binding.rightOptionView.width - easyPopupWindow.width - easyPopupWindow.showAsDropDown(binding.rightOptionView, x, 0) - } + override fun onRightClick() { + easyPopupWindow.showAsDropDown(binding.titleView, binding.titleView.width, 0) + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { - groupId = intent.getStringExtra(Constant.INTENT_PARAM)!! - binding.titleView.text = String.format(groupId + "项目设备列表") + groupId = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY)!! + binding.titleView.setTitle(String.format(groupId + "项目设备列表")) weakReferenceHandler = WeakReferenceHandler(callback) groupViewModel = ViewModelProvider(this)[ProjectGroupViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] obtainDeviceListByPage() + + val menuItems = ArrayList().apply { + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[0], LocaleConstant.POPUP_TITLES[0] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[1], LocaleConstant.POPUP_TITLES[1] + ) + ) + add( + EasyPopupWindow.MenuItem( + LocaleConstant.POPUP_IMAGES[2], LocaleConstant.POPUP_TITLES[2] + ) + ) + } + easyPopupWindow.set(menuItems, object : EasyPopupWindow.OnPopupWindowClickListener { + override fun onPopupItemClicked(position: Int) { + when (position) { + 0 -> { + order = if (order == 0) { + 1 + } else { + 0 + } + pageIndex = 1 + obtainDeviceListByPage() + } + + 1 -> { + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("删除后将无法恢复,是否继续?") + .setNegativeButton("容我想想").setPositiveButton("已经想好") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onCancelClick() { + + } + + override fun onConfirmClick() { + val ids = ArrayList() + dataBeans.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + + } + }).build().show() + } + + 2 -> { + MultiSelectDialog.Builder().setContext(this@GroupDeviceActivity) + .setTitle("选择设备").setDataSource(dataBeans) + .setNegativeButton("取消").setPositiveButton("选好了") + .setOnDialogButtonClickListener(object : + MultiSelectDialog.OnDialogButtonClickListener { + override fun onConfirmClick(selectedModels: MutableList) { + val ids = ArrayList() + selectedModels.forEach { + if (!it.deviceId.isNullOrBlank()) { + ids.add(it.deviceId.toLong()) + } + } + isDeleteAll = true + deviceViewModel.deleteDeviceById(ids) + } + + override fun onCancelClick() { + + } + }).build().show() + } + } + } + }) + easyPopupWindow.setBackgroundDrawable(null) } override fun observeRequestState() { diff --git a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt index 70e49f0..47c0af6 100644 --- a/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/HistoryDataActivity.kt @@ -8,22 +8,20 @@ import com.casic.smarttube.databinding.ActivityHistoryDataBinding import com.casic.smarttube.extensions.dateToMonthDay import com.casic.smarttube.extensions.getQuarterOfYear +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.ChartViewHelper import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.vm.DeviceViewModel import com.casic.smarttube.widgets.DateSelectDialog import com.github.mikephil.charting.data.Entry -import com.gyf.immersionbar.ImmersionBar import com.jzxiang.pickerview.data.Type import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.timestampToDate import com.pengxh.kt.lite.extensions.timestampToLastMonthDate import com.pengxh.kt.lite.extensions.timestampToLastWeekDate -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState import java.util.Calendar class HistoryDataActivity : KotlinBaseActivity() { @@ -38,13 +36,12 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - val params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + val params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! groupId = params[0] devCode = params[1] diff --git a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt index 575e1ee..c7f06c9 100644 --- a/app/src/main/java/com/casic/smarttube/view/MainActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MainActivity.kt @@ -3,31 +3,31 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMainBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.fragment.HomePageFragment import com.casic.smarttube.fragment.MinePageFragment import com.casic.smarttube.fragment.OverviewFragment import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class MainActivity : KotlinBaseActivity() { private var menuItem: MenuItem? = null - private var fragmentList: MutableList = ArrayList() + private var fragmentPages: MutableList = ArrayList() private var clickTime: Long = 0 init { - fragmentList.add(HomePageFragment()) - fragmentList.add(OverviewFragment()) - fragmentList.add(MinePageFragment()) + fragmentPages.add(HomePageFragment()) + fragmentPages.add(OverviewFragment()) + fragmentPages.add(MinePageFragment()) } override fun initViewBinding(): ActivityMainBinding { @@ -36,7 +36,7 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -58,8 +58,7 @@ } false } - binding.mainViewPager.adapter = ViewPagerAdapter(fragmentList, supportFragmentManager) - binding.mainViewPager.offscreenPageLimit = fragmentList.size //缓存页数 + binding.mainViewPager.adapter = ViewPagerAdapter(fragmentPages, supportFragmentManager) } override fun observeRequestState() { @@ -110,5 +109,9 @@ override fun getItem(position: Int): Fragment = viewPages[position] override fun getCount(): Int = viewPages.size + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt index 908aade..00bd76e 100644 --- a/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/MapDeviceBriefActivity.kt @@ -16,15 +16,15 @@ import com.amap.api.services.geocoder.RegeocodeResult import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivityMapDeviceBriefBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.LoadingDialogHub import com.casic.smarttube.utils.RouteOnMap import com.casic.smarttube.vm.DeviceViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.widget.TitleBarView class MapDeviceBriefActivity : KotlinBaseActivity() { @@ -41,9 +41,16 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) - binding.titleInclude.titleView.text = "设备最新数据地图展示" - binding.titleInclude.leftBackView.setOnClickListener { finish() } + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) + binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener { + override fun onLeftClick() { + finish() + } + + override fun onRightClick() { + + } + }) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -55,7 +62,7 @@ uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜角度 uiSettings.isRotateGesturesEnabled = false//不允许地图旋转 - this.params = intent.getStringArrayListExtra(Constant.INTENT_PARAM)!! + this.params = intent.getStringArrayListExtra(LiteKitConstant.INTENT_PARAM_KEY)!! deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] } diff --git a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt index bb0b0ed..4be4a14 100644 --- a/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt +++ b/app/src/main/java/com/casic/smarttube/view/SelectLocationActivity.kt @@ -14,11 +14,9 @@ import com.amap.api.maps.model.MyLocationStyle import com.casic.smarttube.R import com.casic.smarttube.databinding.ActivitySelectLocationBinding +import com.casic.smarttube.extensions.initImmersionBar import com.casic.smarttube.utils.CenterMarkerView -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.convertColor -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class SelectLocationActivity : KotlinBaseActivity(), @@ -34,8 +32,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).init() - ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this)) + binding.rootView.initImmersionBar(this, true, R.color.mainThemeColor) binding.titleView.text = "手动选点" binding.leftBackView.setOnClickListener { finish() } } diff --git a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt index 7ef773f..e35983e 100644 --- a/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/AuthenticateViewModel.kt @@ -8,13 +8,13 @@ import com.casic.smarttube.model.DistrictModel import com.casic.smarttube.model.PublicKeyModel import com.casic.smarttube.model.StreetModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class AuthenticateViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt index 4d8e265..f73d92b 100644 --- a/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/DeviceViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceDetailModel +import com.casic.smarttube.model.DeviceHistoryDataModel +import com.casic.smarttube.model.LastDataModel +import com.casic.smarttube.model.MapDeviceModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class DeviceViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt index 2a50736..de8c83f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/LoginViewModel.kt @@ -6,13 +6,13 @@ import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel import com.casic.smarttube.model.LoginResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class LoginViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt index df95ab5..3477a7f 100644 --- a/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/ProjectGroupViewModel.kt @@ -4,14 +4,18 @@ import com.casic.smarttube.base.BaseApplication import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage -import com.casic.smarttube.model.* -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.model.CommonResultModel +import com.casic.smarttube.model.DeviceListModel +import com.casic.smarttube.model.GroupDeviceModel +import com.casic.smarttube.model.GroupListModel +import com.casic.smarttube.model.ProjectGroupModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class ProjectGroupViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt index b3e7390..0d3faaf 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UploadImageViewModel.kt @@ -5,12 +5,12 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.CommonResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel import java.io.File class UploadImageViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt index 5e44b97..15f0d96 100644 --- a/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/UserViewModel.kt @@ -5,15 +5,15 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.UserDetailModel +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.casic.smarttube.utils.LocaleConstant -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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 import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState class UserViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt index 273d595..0148887 100644 --- a/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/smarttube/vm/VersionViewModel.kt @@ -5,13 +5,13 @@ import com.casic.smarttube.extensions.separateResponseCode import com.casic.smarttube.extensions.toErrorMessage import com.casic.smarttube.model.VersionResultModel -import com.casic.smarttube.utils.retrofit.RetrofitServiceManager +import com.casic.smarttube.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +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.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { diff --git a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt index ae7df77..c052c7f 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/DateSelectDialog.kt @@ -85,7 +85,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_select_date) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt new file mode 100644 index 0000000..6646439 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/EmptyView.kt @@ -0,0 +1,29 @@ +package com.casic.smarttube.widgets + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.casic.smarttube.databinding.WidgetViewEmptyBinding + +class EmptyView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) { + + private var binding: WidgetViewEmptyBinding + + init { + binding = WidgetViewEmptyBinding.inflate(LayoutInflater.from(context), this, true) + binding.reloadButton.setOnClickListener { + listener?.onReloadButtonClicked() + } + } + + private var listener: OnClickListener? = null + + fun setOnClickListener(listener: OnClickListener?) { + this.listener = listener + } + + interface OnClickListener { + fun onReloadButtonClicked() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt index cb9316d..c9030dd 100644 --- a/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt +++ b/app/src/main/java/com/casic/smarttube/widgets/MultiSelectDialog.kt @@ -72,7 +72,7 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85) + this.resetParams(Gravity.CENTER, R.style.UserDefinedAnimation, 0.85f) setContentView(R.layout.dialog_multi_select) setCancelable(false) setCanceledOnTouchOutside(false) diff --git a/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt new file mode 100644 index 0000000..03ab656 --- /dev/null +++ b/app/src/main/java/com/casic/smarttube/widgets/ProgressDialog.kt @@ -0,0 +1,36 @@ +package com.casic.smarttube.widgets + +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import com.casic.smarttube.databinding.DialogProgressBinding +import com.pengxh.kt.lite.R +import com.pengxh.kt.lite.extensions.binding +import com.pengxh.kt.lite.extensions.initDialogLayoutParams + +class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) { + + private val binding: DialogProgressBinding by binding() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(0.5f) + setCanceledOnTouchOutside(false) + setCancelable(false) + binding.progressBar.progress = 0 + binding.progressText.text = "0 %" + } + + fun setMaxProgress(maxProgress: Long) { + binding.progressBar.max = maxProgress.toInt() + } + + private fun getMaxProgress() = binding.progressBar.max + + fun updateProgress(progress: Long) { + binding.progressBar.progress = progress.toInt() + + val percent = (progress.toFloat() / getMaxProgress()) * 100 + binding.progressText.text = String.format("%.2f %%", percent) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/download_progress.xml b/app/src/main/res/drawable/download_progress.xml deleted file mode 100644 index 9704a9f..0000000 --- a/app/src/main/res/drawable/download_progress.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_empty.xml b/app/src/main/res/drawable/ic_empty.xml new file mode 100644 index 0000000..8f39874 --- /dev/null +++ b/app/src/main/res/drawable/ic_empty.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_about_us.xml b/app/src/main/res/layout/activity_about_us.xml index 69dc539..c6c6c6f 100644 --- a/app/src/main/res/layout/activity_about_us.xml +++ b/app/src/main/res/layout/activity_about_us.xml @@ -1,15 +1,19 @@ + android:orientation="vertical"> - + + android:orientation="vertical"> - + + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_right_image="@drawable/ic_navigation" + app:tbv_show_right_image="true" + app:tbv_smaller_title="true" + app:tbv_text="设备详情" /> + android:orientation="vertical"> - - - - - - - - + android:layout_height="wrap_content" + android:background="@color/mainThemeColor" + app:tbv_show_right_image="true" /> + android:orientation="vertical"> - + android:orientation="vertical"> - + @@ -22,7 +23,7 @@ android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" - android:text="@string/app_name" + android:text="手动选点" android:textColor="@color/white" android:textSize="@dimen/sp_18" /> diff --git a/app/src/main/res/layout/dialog_progress.xml b/app/src/main/res/layout/dialog_progress.xml new file mode 100644 index 0000000..6c3f13d --- /dev/null +++ b/app/src/main/res/layout/dialog_progress.xml @@ -0,0 +1,31 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml deleted file mode 100644 index daec7c8..0000000 --- a/app/src/main/res/layout/include_base_title.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/widget_view_empty.xml b/app/src/main/res/layout/widget_view_empty.xml new file mode 100644 index 0000000..f2316ab --- /dev/null +++ b/app/src/main/res/layout/widget_view_empty.xml @@ -0,0 +1,21 @@ + + + + + +