保险服务优化

This commit is contained in:
yezhiqiu
2025-10-20 15:41:39 +08:00
parent 05f62cf33c
commit 0b8561316c
14 changed files with 516 additions and 123 deletions

1
.idea/misc.xml generated
View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">

View File

@@ -1 +1 @@
#Tue Sep 09 14:41:15 CST 2025
#Fri Oct 17 18:14:44 CST 2025

View File

@@ -29,8 +29,8 @@ android {
minSdkVersion 23
targetSdkVersion 35
versionCode 2020
// versionName "2.0.20"
versionName "2.0.20-Beta4"
versionName "2.0.20"
// versionName "2.0.20-Beta5"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View File

@@ -0,0 +1,10 @@
package com.abbidot.tracker.bean
/**
*Created by .yzq on 2025/10/16/周四.
* @link
* @description:
*/
data class CommonDataBean(
var taxRate: Double, var surplusSafeValidMonths: Int, var reactivationFee: Double
)

View File

@@ -3,6 +3,7 @@ package com.abbidot.tracker.retrofit2
import com.abbidot.baselibrary.network.base.BaseResponse
import com.abbidot.tracker.bean.ActiveTimeBean
import com.abbidot.tracker.bean.AlipayOrderBean
import com.abbidot.tracker.bean.CommonDataBean
import com.abbidot.tracker.bean.CountryCodeBean
import com.abbidot.tracker.bean.DeviceBean
import com.abbidot.tracker.bean.DeviceDetailBean
@@ -55,7 +56,7 @@ interface INetworkService {
//亚马逊服务器(国外ip)
const val BASE_URL_ABROAD = "https://aws.abbidot.com/abbidot/"
// const val BASE_URL_ABROAD = "http://192.168.0.229:8080/abbidot/"
// const val BASE_URL_ABROAD = "http://192.168.0.220:8080/abbidot/"
// const val BASE_URL_ABROAD = "$IP_SERVER:8443/abbidotServer/"
//亚马逊服务器(国内ip)
@@ -1267,7 +1268,15 @@ interface INetworkService {
@GET("order$SUBSCRIPTIONS_V3/reactivation/fee")
suspend fun getReactivationFee(
@Query("orderId") orderId: String
): BaseResponse<Double>
): BaseResponse<CommonDataBean>
/**
* 获取具体国家地区税率
*/
@GET("order$SUBSCRIPTIONS_V3/plan/getTaxRateByRegionName")
suspend fun getTaxRateByRegionName(
@Query("countryCode") countryCode: String, @Query("regionName") regionName: String
): BaseResponse<CommonDataBean>
/**
* 创建Stripe订单发起支付

View File

@@ -1143,6 +1143,13 @@ object NetworkApi : BaseNetworkApi<INetworkService>(INetworkService.BASE_URL) {
service.updateSubscriptionStatus(subscriptionId, status)
}
/**
* 获取具体国家地区税率
*/
suspend fun getTaxRateByRegionName(countryCode: String, regionName: String) = getResult {
service.getTaxRateByRegionName(countryCode, regionName)
}
/**
* 获取SIM卡重新激活费用
*/

View File

@@ -139,22 +139,27 @@ class ChoosePlanActivity :
}
}
private fun goSureSubscriptionPlan() {
Util.checkLocationPermissionsGpsEnabled(mContext, {
Intent(
mContext, SureSubscriptionPlanActivity::class.java
).let {
if (mChoosePlanAdapter.getData().isNotEmpty()) {
val cPlan = mChoosePlanAdapter.getData()[mSelectPlanIndex]
it.putExtra(ConstantString.SetMeal, cPlan)
it.putExtra(ConstantString.Upgrade, isUpgrade)
it.putExtra(ConstantString.LkSetMeal, mOrderBean)
it.putExtra(ConstantString.RechargeType, mRechargeType)
startActivity(it)
}
}
})
}
override fun onClick(v: View?) {
mViewBinding.apply {
when (v!!) {
btnSelectChoosePlanContinue -> Intent(
mContext, SureSubscriptionPlanActivity::class.java
).let {
if (mChoosePlanAdapter.getData().isNotEmpty()) {
val cPlan = mChoosePlanAdapter.getData()[mSelectPlanIndex]
it.putExtra(ConstantString.SetMeal, cPlan)
it.putExtra(ConstantString.Upgrade, isUpgrade)
it.putExtra(ConstantString.LkSetMeal, mOrderBean)
it.putExtra(ConstantString.RechargeType, mRechargeType)
startActivity(it)
}
}
btnSelectChoosePlanContinue -> goSureSubscriptionPlan()
}
}
}

View File

@@ -25,6 +25,8 @@ import com.abbidot.tracker.databinding.ActivitySureSubscriptionPlanBinding
import com.abbidot.tracker.ui.activity.WebViewActivity
import com.abbidot.tracker.util.Util
import com.abbidot.tracker.util.ViewUtil
import com.abbidot.tracker.vm.GeoCoderViewModel
import com.abbidot.tracker.vm.GoogleLocationViewModel
import com.abbidot.tracker.vm.SubscriptionManageViewModel
import kotlin.math.abs
@@ -32,6 +34,8 @@ class SureSubscriptionPlanActivity :
BaseActivity<ActivitySureSubscriptionPlanBinding>(ActivitySureSubscriptionPlanBinding::inflate) {
private val mSubscriptionViewModel: SubscriptionManageViewModel by viewModels()
private val mGoogleLocationViewModel: GoogleLocationViewModel by viewModels()
private val mGeoCoderViewModel: GeoCoderViewModel by viewModels()
private var mPackageBean: PackageBean? = null
private var mOrderBean: SubscriptionsOrderBean? = null
@@ -43,7 +47,7 @@ class SureSubscriptionPlanActivity :
private var mSumInsuranceMoney = 0.0
//税率
private val mTaxRate = 0.0825
private var mTaxRate = 0.0825
//付款的总金额(含税)
private var mTotalWithTaxMoney = 0.0
@@ -81,21 +85,21 @@ class SureSubscriptionPlanActivity :
mSummaryAdapter = SureSubscribeSummaryAdapter(this, mutableListOf())
mOrderBean?.let {
if (isUpgrade) {
it.isUpdateOrder = ConstantInt.Type1
//套餐总天数
val totalDay = if (it.mealUnit == ConstantString.PackageUnitYear) {
it.mealPeriod * 365
} else {
30 * it.planTimeMonthsCount
}
mResidualMoney =
((it.totalAmountWithTax - it.tax - it.reactivatePrice) / totalDay) * it.surplusDays
} else {
it.isUpdateOrder = ConstantInt.Type0
}
}
// mOrderBean?.let {
// if (isUpgrade) {
// it.isUpdateOrder = ConstantInt.Type1
// //套餐总天数
// val totalDay = if (it.mealUnit == ConstantString.PackageUnitYear) {
// it.mealPeriod * 365
// } else {
// 30 * it.planTimeMonthsCount
// }
// mResidualMoney =
// ((it.totalAmountWithTax - it.tax - it.reactivatePrice) / totalDay) * it.surplusDays
// } else {
// it.isUpdateOrder = ConstantInt.Type0
// }
// }
mViewBinding.apply {
ViewUtil.instance.setRecyclerViewVerticalLinearLayout(
@@ -105,7 +109,186 @@ class SureSubscriptionPlanActivity :
bottom = AppUtils.dpToPx(4)
)
// mOrderBean?.let {
// ilSubscribePlanDetail.tvSureSubscribePlanDeviceId.text = it.deviceOutId
// val nowTimestamp = System.currentTimeMillis()
//
// mPackageBean?.let { p ->
// ilSubscribePlanDetail.tvSureSubscribePlanPer.text = String.format(
// getString(R.string.txt_month_unit), "${p.planTimeMonthsCount}"
// )
// val renewalString = if (p.mealUnit == ConstantString.PackageUnitYear) {
//// ilSubscribePlanDetail.tvSureSubscribePlanPer.text =
//// String.format(getString(R.string.txt_year_unit), p.period)
// val renewalTimestamp =
// Utils.getAfterHowTimestamp(nowTimestamp, p.period * 365L)
// val renewalDate =
// Utils.formatTime(renewalTimestamp, Utils.DATE_FORMAT_PATTERN_EN7)
// if (p.period > 1) {
// String.format(
// getString(R.string.txt_renewal_years),
// "${p.autoRenewPrice}",
// "${p.period}",
// renewalDate
// )
// } else {
// String.format(
// getString(R.string.txt_renewal_year),
// "${p.autoRenewPrice}",
// renewalDate
// )
// }
// } else {
// val renewalTimestamp =
// Utils.getAfterHowTimestamp(nowTimestamp, 30L * p.planTimeMonthsCount)
// val renewalDate =
// Utils.formatTime(renewalTimestamp, Utils.DATE_FORMAT_PATTERN_EN7)
// if (p.planTimeMonthsCount > 1) {
// String.format(
// getString(R.string.txt_renewal_months),
// "${p.autoRenewPrice}",
// "${p.planTimeMonthsCount}",
// renewalDate
// )
// } else {
// String.format(
// getString(R.string.txt_renewal_month),
// "${p.autoRenewPrice}",
// renewalDate
// )
// }
// }
// ilSubscribePlanDetail.tvSureSubscribePlanUnderused.text = renewalString
// ilSubscribePlanDetail.tvSureSubscribePlanMoneySum.text = String.format(
// getString(R.string.txt_money_unit), "${p.autoRenewPrice}"
// )
//
// val packageName = "${p.planName}(${p.planCategory})"
// ilSubscribePlanDetail.tvSureSubscribePlanName.text = packageName
// val price = p.planPrice
//// val price = if (p.discountedPrice > 0.0) p.discountedPrice else p.planPrice
// val priceString = String.format(
// getString(R.string.txt_money_unit),
// Utils.formatDecimal(price / p.planTimeMonthsCount, 1)
// )
// ilSubscribePlanDetail.tvSureSubscribePlanMoney.text = priceString
//
// ViewUtil.instance.addMenuBean(
// mSummaryAdapter.getData(),
// p.planName,
// "$price",
// colorRedId = R.color.data_black_color
// )
// mTotalMoney += price
// mSumInsuranceMoney =
// Utils.formatDecimal(p.everyMonthSafeFee * p.period * 12, 1).toDouble()
// ViewUtil.instance.addMenuBean(
// mSummaryAdapter.getData(),
// getString(R.string.txt_annual_care_text),
// "$mSumInsuranceMoney",
// colorRedId = R.color.data_black_color
// )
// mTotalMoney += mSumInsuranceMoney
//
// val insuranceMoneyString =
// String.format(getString(R.string.txt_month_unit), "${p.period * 12}")
// ilSubscribePlanInsurance.tvSureSubscribePlanInsurancePer.text =
// insuranceMoneyString
// ilSubscribePlanInsurance.tvSureSubscribePlanInsurancePerMoney.text =
// String.format(getString(R.string.txt_money_unit), "${p.everyMonthSafeFee}")
// ilSubscribePlanInsurance.tvSureSubscribePlanInsuranceMoney.text =
// String.format(getString(R.string.txt_money_unit), "$mSumInsuranceMoney")
//
// if (isUpgrade) {
// mTotalMoney -= mResidualMoney
// ViewUtil.instance.addMenuBean(
// mSummaryAdapter.getData(),
// getString(R.string.txt_residual_value),
// Utils.formatDecimal(mResidualMoney, 1),
// colorRedId = R.color.red_color5,
// isSwitch = true
// )
// }
// ViewUtil.instance.addMenuBean(
// mSummaryAdapter.getData(),
// getString(R.string.txt_sales_tax),
// "0",
// colorRedId = R.color.data_black_color
// )
// }
//
// //判断套餐是否过期
// if (!TextUtils.isEmpty(it.orderNum) && it.surplusDays == 0L && it.subscriptionStatus == ConstantInt.Close) {
// mOrderBean?.reactivation = 1
// mSubscriptionViewModel.getReactivationFee(it.orderNum)
// } else {
// mOrderBean?.reactivation = 0
// mOrderBean?.reactivatePrice = 0.0
// updateMoney()
// }
// }
//添加下划线
ilSubscribePlanDetail.tvSureSubscribePlanTermsConditions.paint.flags =
Paint.UNDERLINE_TEXT_FLAG
ilSubscribePlanInsurance.cbSureSubscribeInsureSwitch.setOnCheckedChangeListener { buttonView, isChecked ->
mOrderBean?.let { order ->
if (isUpgrade && order.annualCareType == ConstantInt.Type1) {
ilSubscribePlanInsurance.cbSureSubscribeInsureSwitch.isChecked = !isChecked
showToast(R.string.txt_annual_care_included, gravity = Gravity.CENTER)
return@setOnCheckedChangeListener
}
val list = mSummaryAdapter.getData()
if (isChecked) {
MenuTxtBean(
getString(R.string.txt_annual_care_text), "$mSumInsuranceMoney"
).let {
it.colorRedId = R.color.data_black_color
list.add(1, it)
}
mTotalMoney += mSumInsuranceMoney
} else {
list.removeAt(1)
mTotalMoney -= mSumInsuranceMoney
mSummaryAdapter.notifyItemRemoved(1)
}
updateMoney()
}
}
setOnClickListenerViews(
btnSureSubscribePlan1Continue,
ilSubscribePlanDetail.tvSureSubscribePlanTermsConditions,
ilSubscribePlanInsurance.ivSureSubscribePlanInsurance
)
if (AppUtils.isChina(AppUtils.SWITCH_MAP_TYPE)) {
sureSubscriptionDetail()
} else {
setButtonEnabled(btnSureSubscribePlan1Continue, ConstantInt.Type0)
mGoogleLocationViewModel.getLastLocation(mContext)
}
}
}
private fun sureSubscriptionDetail() {
mViewBinding.apply {
setButtonEnabled(btnSureSubscribePlan1Continue, ConstantInt.Type1)
mOrderBean?.let {
if (isUpgrade) {
it.isUpdateOrder = ConstantInt.Type1
//套餐总天数
val totalDay = if (it.mealUnit == ConstantString.PackageUnitYear) {
it.mealPeriod * 365
} else {
30 * it.planTimeMonthsCount
}
mResidualMoney = (it.autoRenewPrice / totalDay) * it.surplusDays
} else {
it.isUpdateOrder = ConstantInt.Type0
}
ilSubscribePlanDetail.tvSureSubscribePlanDeviceId.text = it.deviceOutId
val nowTimestamp = System.currentTimeMillis()
@@ -155,6 +338,9 @@ class SureSubscriptionPlanActivity :
}
}
ilSubscribePlanDetail.tvSureSubscribePlanUnderused.text = renewalString
ilSubscribePlanDetail.tvSureSubscribePlanMoneySum.text = String.format(
getString(R.string.txt_money_unit), "${p.autoRenewPrice}"
)
val packageName = "${p.planName}(${p.planCategory})"
ilSubscribePlanDetail.tvSureSubscribePlanName.text = packageName
@@ -211,49 +397,22 @@ class SureSubscriptionPlanActivity :
}
//判断套餐是否过期
if (!TextUtils.isEmpty(it.orderNum) && it.surplusDays == 0L && it.subscriptionStatus == ConstantInt.Close) {
mOrderBean?.reactivation = 1
mSubscriptionViewModel.getReactivationFee(it.orderNum)
} else {
// if (!TextUtils.isEmpty(it.orderNum) && it.surplusDays == 0L && it.subscriptionStatus == ConstantInt.Close) {
// mOrderBean?.reactivation = 1
// mSubscriptionViewModel.getReactivationFee(it.orderNum)
// } else {
// mOrderBean?.reactivation = 0
// mOrderBean?.reactivatePrice = 0.0
// updateMoney()
// }
if (TextUtils.isEmpty(it.orderNum)) {
mOrderBean?.reactivation = 0
mOrderBean?.reactivatePrice = 0.0
updateMoney()
} else {
mSubscriptionViewModel.getReactivationFee(it.orderNum)
}
}
//添加下划线
ilSubscribePlanDetail.tvSureSubscribePlanTermsConditions.paint.flags =
Paint.UNDERLINE_TEXT_FLAG
ilSubscribePlanInsurance.cbSureSubscribeInsureSwitch.setOnCheckedChangeListener { buttonView, isChecked ->
mOrderBean?.let { order ->
if (isUpgrade && order.annualCareType == ConstantInt.Type1) {
ilSubscribePlanInsurance.cbSureSubscribeInsureSwitch.isChecked = !isChecked
showToast(R.string.txt_annual_care_included, gravity = Gravity.CENTER)
return@setOnCheckedChangeListener
}
val list = mSummaryAdapter.getData()
if (isChecked) {
MenuTxtBean(
getString(R.string.txt_annual_care_text), "$mSumInsuranceMoney"
).let {
it.colorRedId = R.color.data_black_color
list.add(1, it)
}
mTotalMoney += mSumInsuranceMoney
} else {
list.removeAt(1)
mTotalMoney -= mSumInsuranceMoney
mSummaryAdapter.notifyItemRemoved(1)
}
updateMoney()
}
}
setOnClickListenerViews(
btnSureSubscribePlan1Continue,
ilSubscribePlanDetail.tvSureSubscribePlanTermsConditions,
ilSubscribePlanInsurance.ivSureSubscribePlanInsurance
)
}
}
@@ -267,9 +426,10 @@ class SureSubscriptionPlanActivity :
XEventBus.post(EventName.RefreshPackage)
finish()
}
mSubscriptionViewModel.mReactivationFeeLiveData.observe(this) {
dealRequestResult(it, object : GetResultCallback {
override fun onResult(any: Any) {
mSubscriptionViewModel.apply {
mReactivationFeeLiveData.observe(this@SureSubscriptionPlanActivity) {
dealRequestResult(it, object : GetResultCallback {
override fun onResult(any: Any) {
// it.getOrNull()?.apply {
// mOrderBean?.reactivatePrice = this
// mSummaryAdapter.getData().add(
@@ -280,16 +440,64 @@ class SureSubscriptionPlanActivity :
// })
// mTotalMoney += this
// }
updateMoney()
}
})
it.getOrNull()?.apply {
mPackageBean?.let { p ->
mTotalMoney -= mSumInsuranceMoney
val howSafeValidMonths =
p.planTimeMonthsCount - surplusSafeValidMonths
if (howSafeValidMonths > 0) {
val insuranceMoneyString = String.format(
getString(R.string.txt_month_unit), "$howSafeValidMonths"
)
mViewBinding.ilSubscribePlanInsurance.tvSureSubscribePlanInsurancePer.text =
insuranceMoneyString
mSumInsuranceMoney = Utils.formatDecimal(
howSafeValidMonths * p.everyMonthSafeFee, 1
).toDouble()
mTotalMoney += mSumInsuranceMoney
mViewBinding.ilSubscribePlanInsurance.tvSureSubscribePlanInsuranceMoney.text =
String.format(
getString(R.string.txt_money_unit),
"$mSumInsuranceMoney"
)
} else {
mSumInsuranceMoney = 0.0
mViewBinding.ilSubscribePlanInsurance.root.visibility =
View.GONE
}
mSummaryAdapter.getData()[1].menuValue = "$mSumInsuranceMoney"
}
}
updateMoney()
}
})
}
mRegionalTaxRateLiveData.observe(this@SureSubscriptionPlanActivity) {
dealRequestResult(it, object : GetResultCallback {
override fun onResult(any: Any) {
it.getOrNull()?.apply {
mTaxRate = taxRate
sureSubscriptionDetail()
}
}
})
}
}
mGoogleLocationViewModel.mGoogleLocationLiveData.observe(this) {
mGeoCoderViewModel.getLatLonAddress(it.latitude, it.longitude)
}
mGeoCoderViewModel.mLatLonAddressLiveData.observe(this) {
mSubscriptionViewModel.getTaxRateByRegionName(
mGeoCoderViewModel.mCountryCode, mGeoCoderViewModel.mRegion
)
}
}
private fun updateMoney() {
mViewBinding.apply {
val list = mSummaryAdapter.getData()
val taxMoney = Utils.formatDecimal(mTaxRate * mTotalMoney, 1).toDouble()
val taxMoney = abs(Utils.formatDecimal(mTaxRate * mTotalMoney, 1).toDouble())
mOrderBean?.tax = taxMoney
list[list.size - 1].menuValue = taxMoney.toString()
mTotalWithTaxMoney = taxMoney + mTotalMoney
@@ -332,8 +540,10 @@ class SureSubscriptionPlanActivity :
planTimeMonthsCount = cPlan.planTimeMonthsCount
mealUnit = cPlan.mealUnit
planCategory = cPlan.planCategory
// autoRenewPrice = Utils.formatDecimal(cPlan.autoRenewPrice * mTaxRate, 1).toDouble()
autoRenewPrice = cPlan.autoRenewPrice
autoRenewPrice =
Utils.formatDecimal(cPlan.autoRenewPrice + cPlan.autoRenewPrice * mTaxRate, 1)
.toDouble()
// autoRenewPrice = cPlan.autoRenewPrice
mealDesc =
mViewBinding.ilSubscribePlanDetail.tvSureSubscribePlanMoney.text.toString() + mViewBinding.ilSubscribePlanDetail.tvSureSubscribePlanPer.text.toString()
}

View File

@@ -161,6 +161,9 @@ abstract class BaseBaiduMapFragment :
mMapView.onPause()
}
override fun liveDataObserve() {
}
/**
* 卫星标准地图模式切换
@@ -653,7 +656,7 @@ abstract class BaseBaiduMapFragment :
//通过LocationClientOption设置LocationClient相关参数
val option = LocationClientOption()
// 打开gps
option.isOpenGps = true
option.openGps = true
// 设置坐标类型
option.setCoorType(mCoordType)
//设置定位刷新间隔

View File

@@ -883,7 +883,7 @@ abstract class BaseGoogleMapFragment :
// The Fused Location Provider provides access to location APIs.
private val mFusedLocationClient: FusedLocationProviderClient by lazy {
LocationServices.getFusedLocationProviderClient(mContext!!)//
LocationServices.getFusedLocationProviderClient(mContext!!)
}
private var mCancellationTokenSource: CancellationTokenSource? = null

View File

@@ -31,6 +31,12 @@ class GeoCoderViewModel : ViewModel() {
var mLat = 0.0
var mLon = 0.0
//地区、州、省
var mRegion = ""
//国家缩写
var mCountryCode = ""
var mAddress = ""
val mLatLonAddressLiveData = MutableLiveData<String>()
@@ -64,6 +70,8 @@ class GeoCoderViewModel : ViewModel() {
if (AppUtils.isChina(AppUtils.SWITCH_MAP_TYPE)) {
baiduMapReverseGeocoder(latitude, longitude)
} else {
// baiduMapReverseGeocoder(-110.95, 44.65)
// mapBoxReverseGeocoder(42.23, -103.18)
mapBoxReverseGeocoder(latitude, longitude)
}
}
@@ -77,52 +85,59 @@ class GeoCoderViewModel : ViewModel() {
SearchEngine.createSearchEngineWithBuiltInDataProviders(SearchEngineSettings())
}
mMapboxSearchRequestTask?.cancel()
mMapboxSearchRequestTask = mSearchEngine?.search(ReverseGeoOptions(
center = Point.fromLngLat(longitude, latitude)
), object : SearchCallback {
override fun onError(e: Exception) {
LogUtil.e(" Mapbox反地理编码error,${e.message}")
mMapboxSearchRequestTask = mSearchEngine?.search(
ReverseGeoOptions(
center = Point.fromLngLat(longitude, latitude)
), object : SearchCallback {
override fun onError(e: Exception) {
LogUtil.e(" Mapbox反地理编码error,${e.message}")
// mLatLonAddressLiveData.value = ""
baiduMapReverseGeocoder(latitude, longitude)
}
baiduMapReverseGeocoder(latitude, longitude)
}
override fun onResults(
results: List<SearchResult>, responseInfo: ResponseInfo
) {
LogUtil.e(results.toString())
if (results.isNotEmpty()) {
val searchResult = results[0]
var address = ""
searchResult.address?.let {
if (!TextUtils.isEmpty(it.street)) {
address += "${it.street} "
override fun onResults(
results: List<SearchResult>, responseInfo: ResponseInfo
) {
LogUtil.e(results.toString())
if (results.isNotEmpty()) {
val searchResult = results[0]
var address = ""
searchResult.metadata?.let {
it.countryIso1?.let { countryCode ->
mCountryCode = countryCode.uppercase()
}
}
searchResult.address?.let {
if (!TextUtils.isEmpty(it.street)) {
address += "${it.street} "
}
// if (!TextUtils.isEmpty(it.houseNumber)) {
// address += "${it.houseNumber} "
// }
if (!TextUtils.isEmpty(it.locality)) {
address += "${it.locality} "
if (!TextUtils.isEmpty(it.locality)) {
address += "${it.locality} "
}
if (!TextUtils.isEmpty(it.place)) {
address += "${it.place} "
}
if (isShowDetailAddress && !TextUtils.isEmpty(it.region)) {
address += "${it.region} "
}
if (isShowDetailAddress && !TextUtils.isEmpty(it.country)) {
address += "${it.country}"
}
mRegion = it.region.toString()
}
if (!TextUtils.isEmpty(it.place)) {
address += "${it.place} "
}
if (isShowDetailAddress && !TextUtils.isEmpty(it.region)) {
address += "${it.region} "
}
if (isShowDetailAddress && !TextUtils.isEmpty(it.country)) {
address += "${it.country}"
}
}
// address = address?.replace("null", "")
mAddress = address
LogUtil.e("Mapbox反地理编码:$mAddress")
mLatLonAddressLiveData.value = mAddress
} else {
mAddress = address
LogUtil.e("Mapbox反地理编码:$mAddress")
mLatLonAddressLiveData.value = mAddress
} else {
// mLatLonAddressLiveData.value = ""-
baiduMapReverseGeocoder(latitude, longitude)
baiduMapReverseGeocoder(latitude, longitude)
}
}
}
})
})
}
/**
@@ -164,6 +179,8 @@ class GeoCoderViewModel : ViewModel() {
if (!TextUtils.isEmpty(streetNumber)) {
address += streetNumber
}
mRegion = province
mCountryCode = countryCodeIso2.uppercase()
LogUtil.e("百度地图反向地理编码详细地址,${streetNumber},${town},${street},$result")
}
//详细地址

View File

@@ -0,0 +1,104 @@
package com.abbidot.tracker.vm
import android.annotation.SuppressLint
import android.content.Context
import android.location.Location
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.abbidot.baselibrary.util.LogUtil
import com.abbidot.tracker.util.LonAndLatUtil
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
import com.google.android.gms.tasks.CancellationTokenSource
import com.google.android.gms.tasks.Task
/**
*Created by .yzq on 2025/10/16/周四.
* @link
* @description:
*/
class GoogleLocationViewModel : ViewModel() {
val mGoogleLocationLiveData = MutableLiveData<Location>()
// The Fused Location Provider provides access to location APIs.
private var mFusedLocationClient: FusedLocationProviderClient? = null
private var mCancellationTokenSource: CancellationTokenSource? = null
/**
* 获取最后位置,用户当前的位置
*/
@SuppressLint("MissingPermission")
fun getLastLocation(context: Context) {
if (null == mFusedLocationClient) {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
}
mFusedLocationClient!!.lastLocation.addOnCompleteListener { taskLocation ->
var location: Location? = null
if (taskLocation.isSuccessful && taskLocation.result != null) {
location = taskLocation.result
LonAndLatUtil.currentUserGPSLat = location.latitude
LonAndLatUtil.currentUserGPSLon = location.longitude
LogUtil.e("Google,getLastLocation${location.latitude}, ${location.longitude}")
} else {
LogUtil.e("Google,getLastLocation:exception" + taskLocation.exception)
}
location?.let {
mGoogleLocationLiveData.value = it
}
if (null == location) requestCurrentLocation(context)
}
}
/**
* 请求用户当前的位置
*/
@SuppressLint("MissingPermission")
private fun requestCurrentLocation(context: Context) {
try {
if (null == mFusedLocationClient) {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
}
if (null == mCancellationTokenSource) {
mCancellationTokenSource = CancellationTokenSource()
}
// val currentLocationTask = mFusedLocationClient.getCurrentLocation(
// LocationRequest.PRIORITY_HIGH_ACCURACY, mCancellationTokenSource!!.token
// )
val currentLocationTask = mFusedLocationClient!!.getCurrentLocation(
Priority.PRIORITY_HIGH_ACCURACY, mCancellationTokenSource!!.token
)
currentLocationTask.addOnCompleteListener { task: Task<Location> ->
var location: Location? = null
val result = if (task.isSuccessful && task.result != null) {
location = task.result
LonAndLatUtil.currentUserGPSLat = location.latitude
LonAndLatUtil.currentUserGPSLon = location.longitude
"(success): ${location.latitude}, ${location.longitude}"
} else {
val exception = task.exception
"(failure): $exception"
}
LogUtil.e("Google,requestCurrentLocation $result")
location?.let {
mGoogleLocationLiveData.value = it
}
}
} catch (e: Exception) {
LogUtil.e("Google,requestCurrentLocation异常:${e.message}")
}
}
private fun stopLocation() {
mCancellationTokenSource?.cancel()
}
override fun onCleared() {
super.onCleared()
stopLocation()
}
}

View File

@@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.abbidot.baselibrary.constant.MMKVKey
import com.abbidot.baselibrary.util.MMKVUtil
import com.abbidot.tracker.bean.CommonDataBean
import com.abbidot.tracker.bean.OrderBean
import com.abbidot.tracker.bean.PackageBean
import com.abbidot.tracker.bean.PackageTypeBean
@@ -26,8 +27,9 @@ class SubscriptionManageViewModel : ViewModel() {
val mUpdateStatusListLiveData = MutableLiveData<Result<String>>()
val mSubscriptionsHistoryLiveData =
MutableLiveData<Result<MutableList<SubscriptionsOrderBean>>>()
val mReactivationFeeLiveData = MutableLiveData<Result<Double>>()
val mReactivationFeeLiveData = MutableLiveData<Result<CommonDataBean>>()
val mRefundLiveData = MutableLiveData<Result<String>>()
val mRegionalTaxRateLiveData = MutableLiveData<Result<CommonDataBean>>()
fun getSubscriptionsOrder() {
viewModelScope.launch {
@@ -113,4 +115,14 @@ class SubscriptionManageViewModel : ViewModel() {
mReactivationFeeLiveData.value = result
}
}
/**
* 获取具体国家地区税率
*/
fun getTaxRateByRegionName(countryCode: String, regionName: String) {
viewModelScope.launch {
val result = NetworkApi.getTaxRateByRegionName(countryCode, regionName)
mRegionalTaxRateLiveData.value = result
}
}
}

View File

@@ -64,13 +64,30 @@
android:layout_marginTop="@dimen/dp_10"
android:text="@string/txt_renewal_year"
android:textSize="@dimen/textSize14"
app:typeface="@string/roboto_bold_font" />
app:typeface="@string/roboto_regular_font" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/dp_1"
android:layout_below="@id/tv_sure_subscribe_plan_underused"
android:layout_marginTop="@dimen/dp_10"
android:background="@color/block_color" />
<com.abbidot.tracker.widget.TypefaceTextView
android:id="@+id/tv_sure_subscribe_plan_money_sum"
style="@style/my_TextView_style_v2"
android:layout_below="@id/tv_sure_subscribe_plan_underused"
android:layout_alignParentEnd="true"
android:layout_marginTop="@dimen/dp_20"
android:text="@string/txt_money_unit"
android:textColor="@color/select_color"
android:textStyle="bold" />
<com.abbidot.tracker.widget.TypefaceTextView
android:id="@+id/tv_sure_subscribe_plan_terms_conditions"
style="@style/my_TextView_style_v2"
android:layout_below="@id/tv_sure_subscribe_plan_underused"
android:layout_marginTop="@dimen/dp_10"
android:layout_alignTop="@id/tv_sure_subscribe_plan_money_sum"
android:layout_alignBottom="@id/tv_sure_subscribe_plan_money_sum"
android:text="@string/txt_terms_conditions_v2"
android:textColor="@color/select_color"
android:textSize="@dimen/textSize14"