1.围栏和wifi适配百度地图
2.修复首次绑定流程中添加wifi ,定位点未按国内版纠正bug 3.优化百度和谷歌定位全局只使用一个 4.删除未使用字符串,整理多语言
This commit is contained in:
@@ -28,9 +28,9 @@ android {
|
||||
applicationId "com.abbidot.tracker"
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 35
|
||||
versionCode 2400
|
||||
versionName "2.4.0"
|
||||
// versionName "2.4.0-Beta1"
|
||||
versionCode 2500
|
||||
// versionName "2.5.0"
|
||||
versionName "2.5.0-Beta1"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
||||
@@ -87,7 +87,9 @@
|
||||
android:usesPermissionFlags="neverForLocation"
|
||||
tools:targetApi="s" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" /> <!-- 指定微信包名 -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
||||
<!-- 指定微信包名 -->
|
||||
<queries>
|
||||
<package android:name="com.tencent.mm" />
|
||||
</queries>
|
||||
@@ -532,6 +534,14 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".service.BaiduLocationService"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="location" />
|
||||
<service
|
||||
android:name=".service.GoogleLocationService"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="location" />
|
||||
<service
|
||||
android:name=".service.DfuService"
|
||||
android:exported="false"
|
||||
|
||||
@@ -11,7 +11,10 @@ import coil.decode.GifDecoder
|
||||
import coil.decode.ImageDecoderDecoder
|
||||
import com.abbidot.baselibrary.util.AppUtils
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.abbidot.tracker.util.BaiduLocationManager
|
||||
import com.abbidot.tracker.util.CrashHandler
|
||||
import com.abbidot.tracker.util.GoogleLocationManager
|
||||
import com.easysocket.utils.LogUtil
|
||||
import com.hjq.toast.Toaster
|
||||
import com.qmuiteam.qmui.arch.QMUISwipeBackActivityManager
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
@@ -27,7 +30,6 @@ class MyApplication : Application() {
|
||||
|
||||
companion object {
|
||||
lateinit var instance: Application
|
||||
|
||||
//保存地图宠物头像对象在内存中,提高显示速度
|
||||
val mapPetHeadHashMap = hashMapOf<String, Any>()
|
||||
}
|
||||
@@ -46,6 +48,8 @@ class MyApplication : Application() {
|
||||
Toaster.init(this)
|
||||
Toaster.setView(R.layout.toast_my_layout)
|
||||
|
||||
initLocationServer()
|
||||
|
||||
// JPushInterface.setDebugMode(true)
|
||||
// JPushInterface.init(this)
|
||||
|
||||
@@ -79,9 +83,19 @@ class MyApplication : Application() {
|
||||
}.build()
|
||||
//设置全局唯一实例
|
||||
Coil.setImageLoader(imageLoader)
|
||||
}
|
||||
|
||||
CrashHandler().init(this)
|
||||
CrashHandler().init(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initLocationServer() {
|
||||
LogUtil.e("初始化定位服务")
|
||||
//初始化定位服务,需要BaseActivity中startLocation()方法调用启动定位服务
|
||||
if (AppUtils.isChina()) {
|
||||
BaiduLocationManager.init(this)
|
||||
} else {
|
||||
GoogleLocationManager.init(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.abbidot.tracker.base
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -36,6 +35,8 @@ import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.constant.ConstantInt
|
||||
import com.abbidot.tracker.constant.GetResultCallback
|
||||
import com.abbidot.tracker.util.BaiduLocationManager
|
||||
import com.abbidot.tracker.util.GoogleLocationManager
|
||||
import com.abbidot.tracker.util.Util
|
||||
import com.abbidot.tracker.util.ViewUtil
|
||||
import com.baidu.platform.comapi.util.NetworkUtil
|
||||
@@ -590,7 +591,7 @@ abstract class BaseActivity<T : ViewBinding>(val inflater: (inflater: LayoutInfl
|
||||
//服务器返回错误信息
|
||||
val exceptionMessage = it.exceptionOrNull()?.message
|
||||
//服务器返回错误code
|
||||
val exceptionCode= it.exceptionOrNull()?.toString()
|
||||
val exceptionCode = it.exceptionOrNull()?.toString()
|
||||
LogUtil.d("Throwable异常", "code=${exceptionCode},${exceptionMessage}")
|
||||
if (null != exceptionCode) {
|
||||
//处理验证码登录,用户未注册的情况
|
||||
@@ -932,5 +933,28 @@ abstract class BaseActivity<T : ViewBinding>(val inflater: (inflater: LayoutInfl
|
||||
hideSoftKeyboardCallback()
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************监听软键盘弹出,输入框上移end************************************/
|
||||
|
||||
/**
|
||||
* 释放定位服务
|
||||
*/
|
||||
private fun releaseLocationService() {
|
||||
LogUtil.e("释放定位服务")
|
||||
if (AppUtils.isChina()) {
|
||||
BaiduLocationManager.releaseServer(this)
|
||||
} else {
|
||||
GoogleLocationManager.releaseServer(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
//判断是否为“完全退出”场景(例如:用户点击返回键退出应用)
|
||||
//isFinishing:判断 Activity 是否正在被销毁。
|
||||
//isTaskRoot:判断当前 Activity 是否为任务栈的根 Activity(避免其他 Activity 销毁时误触发)
|
||||
if (isFinishing && isTaskRoot) {
|
||||
releaseLocationService()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import com.abbidot.tracker.constant.ConstantInt
|
||||
import com.abbidot.tracker.ui.fragment.map.baidumap.BaseBaiduMapFragment
|
||||
import com.abbidot.tracker.ui.fragment.map.googlemap.BaseGoogleMapFragment
|
||||
import com.abbidot.tracker.util.Util
|
||||
import com.baidu.mapapi.utils.DistanceUtil
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
|
||||
/**
|
||||
@@ -39,7 +38,7 @@ open class BaseMapCommon {
|
||||
fun startRefreshUserLocation(
|
||||
baiduMapFragment: BaseBaiduMapFragment?, googleMapFragment: BaseGoogleMapFragment?
|
||||
) {
|
||||
googleMapFragment?.getLastLocation()
|
||||
// googleMapFragment?.getLastLocation()
|
||||
//百度地图定位成功后,每隔60秒刷新用户位置,无需重复调用
|
||||
}
|
||||
|
||||
@@ -134,11 +133,20 @@ open class BaseMapCommon {
|
||||
context,
|
||||
padding,
|
||||
LatLng(ancillaryLatitude, ancillaryLongitude),
|
||||
LatLng(latitudeCenter, longitudeCenter),
|
||||
LatLng(ancillaryOtherLatitude, ancillaryOtherLongitude)
|
||||
)
|
||||
}
|
||||
baiduMapFragment?.apply {
|
||||
setBaiduMapZoom(getDistanceZoom(radius.toDouble()) + 1)
|
||||
// setBaiduMapZoom(getDistanceZoom(radius.toDouble()) + 1)
|
||||
setLatLngZoom(
|
||||
context,
|
||||
com.baidu.mapapi.model.LatLng(ancillaryLatitude, ancillaryLongitude),
|
||||
com.baidu.mapapi.model.LatLng(latitudeCenter, longitudeCenter),
|
||||
com.baidu.mapapi.model.LatLng(
|
||||
ancillaryOtherLatitude, ancillaryOtherLongitude
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,13 +160,20 @@ open class BaseMapCommon {
|
||||
LatLng(latitudeD, longitudeD)
|
||||
)
|
||||
baiduMapFragment?.apply {
|
||||
setBaiduMapZoom(
|
||||
getDistanceZoom(
|
||||
maxOf(
|
||||
shortDistance, longDistance
|
||||
).toDouble()
|
||||
) + 1
|
||||
setLatLngZoom(
|
||||
context,
|
||||
com.baidu.mapapi.model.LatLng(latitudeA, longitudeA),
|
||||
com.baidu.mapapi.model.LatLng(latitudeB, longitudeB),
|
||||
com.baidu.mapapi.model.LatLng(latitudeC, longitudeC),
|
||||
com.baidu.mapapi.model.LatLng(latitudeD, longitudeD)
|
||||
)
|
||||
// setBaiduMapZoom(
|
||||
// getDistanceZoom(
|
||||
// maxOf(
|
||||
// shortDistance, longDistance
|
||||
// ).toDouble()
|
||||
// ) + 1
|
||||
// )
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,20 +189,29 @@ open class BaseMapCommon {
|
||||
LatLng(latitudeF, longitudeF),
|
||||
)
|
||||
baiduMapFragment?.apply {
|
||||
val minLat =
|
||||
minOf(latitudeA, latitudeB, latitudeC, latitudeD, latitudeE, latitudeF)
|
||||
val maxLat =
|
||||
minOf(latitudeA, latitudeB, latitudeC, latitudeD, latitudeE, latitudeF)
|
||||
val minLon = minOf(
|
||||
longitudeA, longitudeB, longitudeC, longitudeD, longitudeE, longitudeF
|
||||
setLatLngZoom(
|
||||
context,
|
||||
com.baidu.mapapi.model.LatLng(latitudeA, longitudeA),
|
||||
com.baidu.mapapi.model.LatLng(latitudeB, longitudeB),
|
||||
com.baidu.mapapi.model.LatLng(latitudeC, longitudeC),
|
||||
com.baidu.mapapi.model.LatLng(latitudeD, longitudeD),
|
||||
com.baidu.mapapi.model.LatLng(latitudeE, longitudeE),
|
||||
com.baidu.mapapi.model.LatLng(latitudeF, longitudeF),
|
||||
)
|
||||
val maxLon = minOf(
|
||||
longitudeA, longitudeB, longitudeC, longitudeD, longitudeE, longitudeF
|
||||
)
|
||||
val distance = DistanceUtil.getDistance(
|
||||
getBaiduMapLatLng(minLat, minLon), getBaiduMapLatLng(maxLat, maxLon)
|
||||
)
|
||||
setBaiduMapZoom(getDistanceZoom(distance))
|
||||
// val minLat =
|
||||
// minOf(latitudeA, latitudeB, latitudeC, latitudeD, latitudeE, latitudeF)
|
||||
// val maxLat =
|
||||
// minOf(latitudeA, latitudeB, latitudeC, latitudeD, latitudeE, latitudeF)
|
||||
// val minLon = minOf(
|
||||
// longitudeA, longitudeB, longitudeC, longitudeD, longitudeE, longitudeF
|
||||
// )
|
||||
// val maxLon = minOf(
|
||||
// longitudeA, longitudeB, longitudeC, longitudeD, longitudeE, longitudeF
|
||||
// )
|
||||
// val distance = DistanceUtil.getDistance(
|
||||
// getBaiduMapLatLng(minLat, minLon), getBaiduMapLatLng(maxLat, maxLon)
|
||||
// )
|
||||
// setBaiduMapZoom(getDistanceZoom(distance))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ import com.abbidot.tracker.constant.ConstantInt
|
||||
import com.abbidot.tracker.deprecated.ui.activity.profile.FencesAddActivity
|
||||
import com.abbidot.tracker.ui.common.map.FencesMapCommon
|
||||
import com.abbidot.tracker.ui.fragment.map.baidumap.BaseBaiduMapFragment
|
||||
import com.abbidot.tracker.util.LonAndLatUtil.Companion.getMaxLatOrLon
|
||||
import com.abbidot.tracker.util.LonAndLatUtil.Companion.getMinLatOrLon
|
||||
import com.abbidot.tracker.util.Util
|
||||
import com.abbidot.tracker.util.ViewUtil
|
||||
import com.abbidot.tracker.widget.FencesPolygonView
|
||||
@@ -88,8 +86,6 @@ class FencesAddBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
|
||||
if (fencesAddActivity.isEdit) {
|
||||
locationSuccess(null)
|
||||
} else {
|
||||
startLocation()
|
||||
}
|
||||
|
||||
//测试矩形围栏使用的代码
|
||||
@@ -276,27 +272,28 @@ class FencesAddBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
fun setRectMapZoom(
|
||||
rectALatLng: LatLng, rectBLatLng: LatLng, rectCLatLng: LatLng, rectDLatLng: LatLng
|
||||
) {
|
||||
val maxLat = getMaxLatOrLon(
|
||||
rectALatLng.latitude, rectBLatLng.latitude, rectCLatLng.latitude, rectDLatLng.latitude
|
||||
)
|
||||
val maxLon = getMaxLatOrLon(
|
||||
rectALatLng.longitude,
|
||||
rectBLatLng.longitude,
|
||||
rectCLatLng.longitude,
|
||||
rectDLatLng.longitude
|
||||
)
|
||||
val minLat = getMinLatOrLon(
|
||||
rectALatLng.latitude, rectBLatLng.latitude, rectCLatLng.latitude, rectDLatLng.latitude
|
||||
)
|
||||
val minLon = getMinLatOrLon(
|
||||
rectALatLng.longitude,
|
||||
rectBLatLng.longitude,
|
||||
rectCLatLng.longitude,
|
||||
rectDLatLng.longitude
|
||||
)
|
||||
val zoom = getDistanceZoom(LatLng(minLat, minLon), LatLng(maxLat, maxLon))
|
||||
LogUtil.e("百度地图zoom==$zoom")
|
||||
setBaiduMapZoom(zoom)
|
||||
// val maxLat = getMaxLatOrLon(
|
||||
// rectALatLng.latitude, rectBLatLng.latitude, rectCLatLng.latitude, rectDLatLng.latitude
|
||||
// )
|
||||
// val maxLon = getMaxLatOrLon(
|
||||
// rectALatLng.longitude,
|
||||
// rectBLatLng.longitude,
|
||||
// rectCLatLng.longitude,
|
||||
// rectDLatLng.longitude
|
||||
// )
|
||||
// val minLat = getMinLatOrLon(
|
||||
// rectALatLng.latitude, rectBLatLng.latitude, rectCLatLng.latitude, rectDLatLng.latitude
|
||||
// )
|
||||
// val minLon = getMinLatOrLon(
|
||||
// rectALatLng.longitude,
|
||||
// rectBLatLng.longitude,
|
||||
// rectCLatLng.longitude,
|
||||
// rectDLatLng.longitude
|
||||
// )
|
||||
// val zoom = getDistanceZoom(LatLng(minLat, minLon), LatLng(maxLat, maxLon))
|
||||
// LogUtil.e("百度地图zoom==$zoom")
|
||||
// setBaiduMapZoom(zoom)
|
||||
setLatLngZoom(mContext!!, rectALatLng, rectBLatLng, rectCLatLng, rectDLatLng)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,8 +77,6 @@ class NavigationBaiduMapFragment: BaseBaiduMapFragment() {
|
||||
isAnimMoveCamera = false,
|
||||
headBgResId = R.drawable.pic_map_location
|
||||
)
|
||||
|
||||
startLocation()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,8 +72,6 @@ class FencesAddGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
|
||||
if (fencesAddActivity.isEdit) {
|
||||
locationSuccess(null)
|
||||
} else {
|
||||
getLastLocation()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,6 @@ class NavigationGoogleMapFragment: BaseGoogleMapFragment() {
|
||||
refreshPetCurrentLocation(mPetLatLng!!, isAnimMoveCamera = false,
|
||||
headBgResId = R.drawable.pic_map_location)
|
||||
|
||||
getLastLocation()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.abbidot.tracker.service
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import com.abbidot.baselibrary.constant.EventName
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.eventbus.XEventBus
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.abbidot.tracker.util.LonAndLatUtil
|
||||
import com.baidu.location.BDAbstractLocationListener
|
||||
import com.baidu.location.BDLocation
|
||||
import com.baidu.location.LocationClient
|
||||
import com.baidu.location.LocationClientOption
|
||||
|
||||
/**
|
||||
* 百度定位服务
|
||||
*/
|
||||
class BaiduLocationService : Service() {
|
||||
private val mBinder = LocalBinder()
|
||||
private var mLocationClient: LocationClient? = null
|
||||
private var mLocationListener: BDAbstractLocationListener? = null
|
||||
|
||||
//坐标类型,定位SDK默认输出GCJ02坐标,地图SDK默认输出BD09ll坐标。火星GCJ02坐标https://lbsyun.baidu.com/faq/api?title=androidsdk/guide/create-map/location
|
||||
private val mCordType = "GCJ02" // Keep consistent with original coordinate type
|
||||
|
||||
inner class LocalBinder : Binder() {
|
||||
fun getService(): BaiduLocationService = this@BaiduLocationService
|
||||
}
|
||||
|
||||
|
||||
fun startLocation(locationPeriod: Int = 1, needStopLocation: Boolean = false) {
|
||||
if (mLocationClient != null) return
|
||||
mLocationClient = LocationClient(applicationContext).apply {
|
||||
locOption = LocationClientOption().apply {
|
||||
openGps = true
|
||||
setCoorType(mCordType)
|
||||
setScanSpan(locationPeriod * 1000)
|
||||
}
|
||||
|
||||
mLocationListener = object : BDAbstractLocationListener() {
|
||||
override fun onReceiveLocation(location: BDLocation?) {
|
||||
location?.let {
|
||||
LogUtil.e("百度定位成功: ${it.latitude}, ${it.longitude}")
|
||||
if (needStopLocation) stopLocation()
|
||||
//转换为gps经纬度
|
||||
LonAndLatUtil.convertFromGCJ02ToWGS84(it.latitude, it.longitude)
|
||||
.let { (lat, lon) ->
|
||||
MMKVUtil.putDouble(MMKVKey.UserGpsLat, lat)
|
||||
MMKVUtil.putDouble(MMKVKey.UserGpsLon, lon)
|
||||
//Android 百度定位 SDK 中,location.getSpeed() 返回的单位是 公里/小时(km/h)。
|
||||
//注意:
|
||||
//只有 GNSS/卫星定位结果通常才有速度信息。
|
||||
//非 GNSS 定位时可能没有有效速度,默认值是 0.0f。
|
||||
//可先用 location.hasSpeed() 判断是否包含速度信息。
|
||||
//保存速度单位是米/秒(m/s)`
|
||||
MMKVUtil.putFloat(MMKVKey.UserGpsSpeed, (it.speed / 3.6f))
|
||||
}
|
||||
XEventBus.post(EventName.LocationData, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
registerLocationListener(mLocationListener)
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
fun stopLocation() {
|
||||
mLocationClient?.apply {
|
||||
stop()
|
||||
unRegisterLocationListener(mLocationListener)
|
||||
}
|
||||
mLocationClient = null
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder = mBinder
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
stopLocation()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.abbidot.tracker.service
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.location.Location
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import com.abbidot.baselibrary.constant.EventName
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.eventbus.XEventBus
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.google.android.gms.location.FusedLocationProviderClient
|
||||
import com.google.android.gms.location.LocationAvailability
|
||||
import com.google.android.gms.location.LocationCallback
|
||||
import com.google.android.gms.location.LocationRequest
|
||||
import com.google.android.gms.location.LocationResult
|
||||
import com.google.android.gms.location.LocationServices
|
||||
import com.google.android.gms.location.Priority
|
||||
import com.hjq.toast.Toaster
|
||||
|
||||
/**
|
||||
* 谷歌定位服务
|
||||
*/
|
||||
class GoogleLocationService : Service() {
|
||||
private val mBinder = LocalBinder()
|
||||
|
||||
// The Fused Location Provider provides access to location APIs.
|
||||
private var mFusedLocationClient: FusedLocationProviderClient? = null
|
||||
|
||||
inner class LocalBinder : Binder() {
|
||||
fun getService(): GoogleLocationService = this@GoogleLocationService
|
||||
}
|
||||
|
||||
private var mLocationCallback: LocationCallback? = null
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun startLocation() {
|
||||
if (null == mFusedLocationClient) {
|
||||
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
|
||||
}
|
||||
if (null == mLocationCallback) {
|
||||
mLocationCallback = object : LocationCallback() {
|
||||
override fun onLocationResult(locationResult: LocationResult) {
|
||||
locationResult.lastLocation?.let {
|
||||
Toaster.show("谷歌定位成功")
|
||||
LogUtil.e("谷歌定位成功: ${it.latitude}, ${it.longitude}")
|
||||
setLocationData(it)
|
||||
XEventBus.post(EventName.LocationData, it)
|
||||
}
|
||||
// for (location in locationResult.locations) {
|
||||
// // 处理位置信息
|
||||
// val lat = location.latitude
|
||||
// val lng = location.longitude
|
||||
// // 更新 UI 或业务逻辑
|
||||
// }
|
||||
}
|
||||
|
||||
override fun onLocationAvailability(availability: LocationAvailability) {
|
||||
// 当位置可用性发生变化时调用(例如 GPS 信号丢失)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mFusedLocationClient?.apply {
|
||||
// // 设置期望的更新间隔为 20 秒
|
||||
val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 20000L)
|
||||
//请求持续时间。请求在此时间后自动过期并移除。默认为 Long.MAX_VALUE(无限期)。
|
||||
// .setDurationMillis(Long.MAX_VALUE)
|
||||
// 位置变化超过10米才更新
|
||||
.setMinUpdateDistanceMeters(10f)
|
||||
// 设置最大延迟为 30 秒(用于批量处理以省电)
|
||||
.setMaxUpdateDelayMillis(30000L)
|
||||
// 最小更新间隔。应用能处理位置更新的最快频率。如果其他应用请求更高频率,你的应用不会收到比这更快的更新,有助于节省电量
|
||||
// .setMinUpdateIntervalMillis(5000L)
|
||||
.build()
|
||||
|
||||
mLocationCallback?.let { callback ->
|
||||
try {
|
||||
requestLocationUpdates(locationRequest, callback, mainLooper)
|
||||
} catch (e: SecurityException) {
|
||||
// 无定位权限
|
||||
LogUtil.e("GoogleLocationService异常:${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun setLocationData(location: Location) {
|
||||
location.apply {
|
||||
MMKVUtil.putDouble(MMKVKey.UserGpsLat, latitude)
|
||||
MMKVUtil.putDouble(MMKVKey.UserGpsLon, longitude)
|
||||
//单位是米/秒(m/s)
|
||||
MMKVUtil.putFloat(MMKVKey.UserGpsSpeed, speed)
|
||||
}
|
||||
}
|
||||
|
||||
fun stopLocation() {
|
||||
mFusedLocationClient?.let { client ->
|
||||
mLocationCallback?.let { callback ->
|
||||
client.removeLocationUpdates(callback)
|
||||
}
|
||||
}
|
||||
// 回调置空,释放引用防内存泄漏
|
||||
mLocationCallback = null
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder = mBinder
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
stopLocation()
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,8 @@ import com.abbidot.tracker.ui.fragment.data.ActivityV2Fragment
|
||||
import com.abbidot.tracker.ui.fragment.data.RouteV3Fragment
|
||||
import com.abbidot.tracker.ui.fragment.map.MapV3Fragment
|
||||
import com.abbidot.tracker.ui.fragment.pet.PetV2Fragment
|
||||
import com.abbidot.tracker.util.BaiduLocationManager
|
||||
import com.abbidot.tracker.util.GoogleLocationManager
|
||||
import com.abbidot.tracker.util.Util
|
||||
import com.abbidot.tracker.util.ViewUtil
|
||||
import com.abbidot.tracker.util.bluetooth.SRBleUtil
|
||||
@@ -134,6 +136,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
||||
setStatusBarLight()
|
||||
|
||||
mSelectPetPosition = MMKVUtil.getInt(MMKVKey.PetSelectPosition)
|
||||
startUpLocation()
|
||||
|
||||
mViewBinding.homeV2ViewPager2.let {
|
||||
it.adapter = ViewPagerAdapter(mFragments, this).apply {
|
||||
@@ -799,6 +802,32 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始定位
|
||||
*/
|
||||
private fun startUpLocation() {
|
||||
LogUtil.e("开始定位")
|
||||
if (AppUtils.isChina()) {
|
||||
//30秒定位一次,定位精度为高精度
|
||||
BaiduLocationManager.startLocation(30)
|
||||
} else {
|
||||
GoogleLocationManager.startLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止定位
|
||||
*/
|
||||
private fun stopUpLocation() {
|
||||
LogUtil.e("停止定位")
|
||||
if (AppUtils.isChina()) {
|
||||
BaiduLocationManager.stopLocation()
|
||||
} else {
|
||||
GoogleLocationManager.stopLocation()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// override fun onTrimMemory(level: Int) {
|
||||
// super.onTrimMemory(level)
|
||||
// LogUtil.e("系统级别:$level"+printLevel(level))
|
||||
@@ -839,8 +868,8 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
LogUtil.e("HomeV2Activity---------------onDestroy")
|
||||
stopUpLocation()
|
||||
stopCountDownConBle()
|
||||
// mSocketUtilManage?.destroy()
|
||||
mBleListenerReceiver?.let {
|
||||
unregisterReceiver(it)
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ class AddPairedSuccessActivity :
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
}, 1500)
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// override fun onRequestError(exceptionCode: String?) {
|
||||
|
||||
@@ -77,8 +77,7 @@ open class AddAndEditFencesZoneBaseActivity :
|
||||
private var isBlockedClick = false
|
||||
|
||||
private var mShowCenterLocationType = ConstantInt.OtherLocationType
|
||||
private val mDefaultFencesName =
|
||||
arrayOf("Home", "Office", "Garden", "Park", "Play", "Unsafe", "Vegetable Garden", "Water")
|
||||
private val mDefaultFencesName = mutableListOf<String>()
|
||||
|
||||
//是否是卫星地图
|
||||
private var isSatelliteMap = false
|
||||
@@ -146,12 +145,12 @@ open class AddAndEditFencesZoneBaseActivity :
|
||||
addListData()
|
||||
|
||||
mFencesZoneShapeAdapter =
|
||||
VirtualFencesZoneShadeAdapter(mContext, mFencesZoneShapeList).apply {
|
||||
setOnItemClickListener(object : BaseRecyclerAdapter.OnItemClickListener {
|
||||
VirtualFencesZoneShadeAdapter(mContext, mFencesZoneShapeList).let {
|
||||
it.setOnItemClickListener(object : BaseRecyclerAdapter.OnItemClickListener {
|
||||
override fun onItemClick(itemView: View?, pos: Int) {
|
||||
if (mFencesZoneShapeList[pos].selected) return
|
||||
ViewUtil.instance.updateDataBeanOnlySelectedItem(
|
||||
this@apply, mFencesZoneShapeList, pos
|
||||
it, mFencesZoneShapeList, pos
|
||||
)
|
||||
setFenceShape(pos + 1)
|
||||
mFencesMapCommon.calculateDistanceAndGetPointLatLng(
|
||||
@@ -159,23 +158,25 @@ open class AddAndEditFencesZoneBaseActivity :
|
||||
)
|
||||
}
|
||||
})
|
||||
it
|
||||
}
|
||||
ViewUtil.instance.setRecyclerViewFlexboxLayout(
|
||||
mContext, rvFencesZoneShapeList, mFencesZoneShapeAdapter
|
||||
)
|
||||
|
||||
mSelectTypeShadeAdapter =
|
||||
SelectFencesTypeCardShadeAdapter(mContext, mFencesZoneTypeList).apply {
|
||||
setOnItemClickListener(object : BaseRecyclerAdapter.OnItemClickListener {
|
||||
SelectFencesTypeCardShadeAdapter(mContext, mFencesZoneTypeList).let {
|
||||
it.setOnItemClickListener(object : BaseRecyclerAdapter.OnItemClickListener {
|
||||
override fun onItemClick(itemView: View?, pos: Int) {
|
||||
ViewUtil.instance.updateDataBeanOnlySelectedItem(
|
||||
this@apply, mFencesZoneTypeList, pos
|
||||
it, mFencesZoneTypeList, pos
|
||||
)
|
||||
if (mFencesBean.fenceType == 2) mFencesBean.fenceNameType = pos + 6
|
||||
else mFencesBean.fenceNameType = pos + 1
|
||||
setFenceName()
|
||||
}
|
||||
})
|
||||
it
|
||||
}
|
||||
ViewUtil.instance.setRecyclerViewGridLayout(
|
||||
mContext, rvFencesZoneImageTypeList, mSelectTypeShadeAdapter, 5
|
||||
@@ -335,18 +336,22 @@ open class AddAndEditFencesZoneBaseActivity :
|
||||
* 地图上画已添加的围栏
|
||||
*/
|
||||
fun drawFences() {
|
||||
mFencesList?.apply {
|
||||
nogoFenceList?.let {
|
||||
mHaveFencesList.addAll(it.toList())
|
||||
}
|
||||
normalFenceList?.let {
|
||||
mHaveFencesList.addAll(it.toList())
|
||||
}
|
||||
//延时执行,等待地图渲染完成
|
||||
mViewBinding.root.postDelayed({
|
||||
mFencesList?.apply {
|
||||
nogoFenceList?.let {
|
||||
mHaveFencesList.addAll(it.toList())
|
||||
}
|
||||
normalFenceList?.let {
|
||||
mHaveFencesList.addAll(it.toList())
|
||||
}
|
||||
|
||||
if (mHaveFencesList.isNotEmpty()) mFencesMapViewModel.setImageFencesData(
|
||||
mContext, mHaveFencesList, mFragment, isSatelliteMap = isSatelliteMap
|
||||
)
|
||||
}
|
||||
}, 200)
|
||||
|
||||
if (mHaveFencesList.size > 0) mFencesMapViewModel.setImageFencesData(
|
||||
mContext, mHaveFencesList, mFragment, isSatelliteMap = isSatelliteMap
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,6 +530,15 @@ open class AddAndEditFencesZoneBaseActivity :
|
||||
}
|
||||
|
||||
private fun addListData() {
|
||||
mDefaultFencesName.add(getString(R.string.txt_home))
|
||||
mDefaultFencesName.add(getString(R.string.txt_office))
|
||||
mDefaultFencesName.add(getString(R.string.txt_garden))
|
||||
mDefaultFencesName.add(getString(R.string.txt_park))
|
||||
mDefaultFencesName.add(getString(R.string.txt_play))
|
||||
mDefaultFencesName.add(getString(R.string.txt_unsafe))
|
||||
mDefaultFencesName.add(getString(R.string.txt_vegetable_garden))
|
||||
mDefaultFencesName.add(getString(R.string.txt_water))
|
||||
|
||||
mFencesZoneShapeList = mutableListOf()
|
||||
with(DataBean()) {
|
||||
imageId = R.drawable.icon_fence_circle_shape_svg
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.abbidot.tracker.ui.activity.device.wifi
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.wifi.WifiManager
|
||||
import android.provider.Settings
|
||||
@@ -48,7 +47,7 @@ class AddWifiPowerZone2Activity :
|
||||
else setLeftBackImage(R.drawable.icon_white_back_svg)
|
||||
|
||||
mWifiZone2MapCommon = WifiZone2MapCommon()
|
||||
mFragment = mWifiZone2MapCommon.getMapFragment(mContext)
|
||||
mFragment = mWifiZone2MapCommon.getMapFragment(mContext, isFirstBind)
|
||||
|
||||
mViewBinding.apply {
|
||||
tvWifiZone2LaterBtn.visibility = if (isFirstBind) View.VISIBLE
|
||||
@@ -80,7 +79,7 @@ class AddWifiPowerZone2Activity :
|
||||
mPetBean?.let {
|
||||
if (it.deviceType == ConstantInt.Type2) {
|
||||
val wifiManager =
|
||||
applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
applicationContext.getSystemService(WIFI_SERVICE) as WifiManager
|
||||
if (!wifiManager.isWifiEnabled) {
|
||||
val intent = Intent(Settings.ACTION_WIFI_SETTINGS)
|
||||
startActivity(intent)
|
||||
@@ -105,9 +104,11 @@ class AddWifiPowerZone2Activity :
|
||||
override fun onClick(v: View?) {
|
||||
mViewBinding.apply {
|
||||
when (v!!) {
|
||||
btnAddWifiZone2Next -> Util.checkBluetoothPermissionsEnabled(this@AddWifiPowerZone2Activity, {
|
||||
goNext()
|
||||
})
|
||||
btnAddWifiZone2Next -> Util.checkBluetoothPermissionsEnabled(
|
||||
this@AddWifiPowerZone2Activity,
|
||||
{
|
||||
goNext()
|
||||
})
|
||||
|
||||
tvWifiZone2LaterBtn -> {
|
||||
// XEventBus.post(EventName.RefreshWiFiZone)
|
||||
|
||||
@@ -229,7 +229,7 @@ class PaymentSuccessActivity :
|
||||
}
|
||||
startActivity(intent)
|
||||
}
|
||||
}, 1500)
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.content.Intent
|
||||
import android.graphics.Paint
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.RadioGroup
|
||||
import androidx.activity.viewModels
|
||||
import com.abbidot.baselibrary.constant.EventName
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
@@ -28,7 +27,6 @@ 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 com.abbidot.tracker.widget.TypefaceRoundButton
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import kotlin.math.abs
|
||||
|
||||
@@ -493,28 +491,28 @@ class SureSubscriptionPlanActivity :
|
||||
mViewBinding.apply {
|
||||
when (v!!) {
|
||||
btnSureSubscribePlan1Continue -> {
|
||||
if (AppUtils.isChina()) {
|
||||
if (null == mRechargePayOptionsCn) {
|
||||
mRechargePayOptionsCn = ViewUtil.instance.showBottomSheet(
|
||||
mContext,
|
||||
R.layout.layout_recharge_pay_options_cn
|
||||
).apply {
|
||||
setOnClickListenerViews(findViewById<TypefaceRoundButton>(R.id.btn_pay_cn_chose_sure))
|
||||
findViewById<RadioGroup>(R.id.rg_pay_cn_chose)?.let {
|
||||
it.setOnCheckedChangeListener { _, checkedId ->
|
||||
when (checkedId) {
|
||||
R.id.rb_pay_cn_chose_alipay -> mPayCnOption =
|
||||
ConstantInt.Type0
|
||||
|
||||
R.id.rb_pay_cn_chose_wxpay -> mPayCnOption =
|
||||
ConstantInt.Type1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// if (AppUtils.isChina()) {
|
||||
// if (null == mRechargePayOptionsCn) {
|
||||
// mRechargePayOptionsCn = ViewUtil.instance.showBottomSheet(
|
||||
// mContext,
|
||||
// R.layout.layout_recharge_pay_options_cn
|
||||
// ).apply {
|
||||
// setOnClickListenerViews(findViewById<TypefaceRoundButton>(R.id.btn_pay_cn_chose_sure))
|
||||
// findViewById<RadioGroup>(R.id.rg_pay_cn_chose)?.let {
|
||||
// it.setOnCheckedChangeListener { _, checkedId ->
|
||||
// when (checkedId) {
|
||||
// R.id.rb_pay_cn_chose_alipay -> mPayCnOption =
|
||||
// ConstantInt.Type0
|
||||
//
|
||||
// R.id.rb_pay_cn_chose_wxpay -> mPayCnOption =
|
||||
// ConstantInt.Type1
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
createOrder()
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.base.BaseMapCommon
|
||||
import com.abbidot.tracker.bean.WiFiZoneBean
|
||||
import com.abbidot.tracker.constant.ConstantInt
|
||||
import com.abbidot.tracker.deprecated.ui.fragment.map.baidumap.NavigationBaiduMapFragment
|
||||
import com.abbidot.tracker.ui.fragment.map.baidumap.EditWiFiZoneBaiduFragment
|
||||
import com.abbidot.tracker.ui.fragment.map.googlemap.EditWiFiZoneGoogleMapFragment
|
||||
|
||||
/**
|
||||
@@ -18,13 +18,14 @@ import com.abbidot.tracker.ui.fragment.map.googlemap.EditWiFiZoneGoogleMapFragme
|
||||
class EditWifiZoneMapCommon : BaseMapCommon() {
|
||||
|
||||
private var mEditZoneGoogleMapFragment: EditWiFiZoneGoogleMapFragment? = null
|
||||
private var mBaiduMapFragment: NavigationBaiduMapFragment? = null
|
||||
private var mBaiduMapFragment: EditWiFiZoneBaiduFragment? = null
|
||||
|
||||
fun getMapFragment(
|
||||
context: Context, wiFiZoneBean: WiFiZoneBean, mapLoadOk: () -> Unit
|
||||
): Fragment {
|
||||
return if (AppUtils.isChina(AppUtils.SWITCH_MAP_TYPE)) {
|
||||
mBaiduMapFragment = NavigationBaiduMapFragment.newInstance(context)
|
||||
mBaiduMapFragment =
|
||||
EditWiFiZoneBaiduFragment.newInstance(context, wiFiZoneBean, mapLoadOk)
|
||||
mBaiduMapFragment!!
|
||||
} else {
|
||||
mEditZoneGoogleMapFragment =
|
||||
@@ -41,6 +42,14 @@ class EditWifiZoneMapCommon : BaseMapCommon() {
|
||||
moveCameraLocation(lat, lon)
|
||||
addImageMarker(lat, lon, R.drawable.icon_location_svg, false, isDraggable)
|
||||
}
|
||||
mBaiduMapFragment?.apply {
|
||||
moveCameraLocation(lat, lon)
|
||||
addImageMarker(
|
||||
lat, lon, R.drawable.icon_location_svg,
|
||||
needConvertGCJ02 = true,
|
||||
anchorCenter = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -135,7 +135,7 @@ class FencesAddEditMapCommon : BaseMapCommon() {
|
||||
if (null != mFencesGoogleMapFragment) {
|
||||
mFencesGoogleMapFragment?.mapOkAndDistancePointLatLng(delayMillis)
|
||||
} else if (null != mFencesBaiduMapFragment) {
|
||||
mFencesBaiduMapFragment?.mapOkAndDistancePointLatLng()
|
||||
mFencesBaiduMapFragment?.mapOkAndDistancePointLatLng(delayMillis)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,21 +117,18 @@ class HistoryDataMapCommon : BaseMapCommon() {
|
||||
}
|
||||
}
|
||||
|
||||
fun showInfoWindow(historyDataBean: HistoryDataBean) {
|
||||
if (null != mHistoryDataBaiduMapFragment) {
|
||||
mHistoryDataBaiduMapFragment!!.showMarkerInfoWindow(historyDataBean)
|
||||
} else if (null != mHistoryDataGoogleMapFragment) {
|
||||
mHistoryDataGoogleMapFragment!!.showMarkerInfoWindow(historyDataBean)
|
||||
}
|
||||
}
|
||||
|
||||
fun resetMarkerInfoViewOffset() {
|
||||
mHistoryDataGoogleMapFragment?.resetMarkerInfoViewOffset()
|
||||
}
|
||||
|
||||
fun setPetUserLatLng() {
|
||||
if (null != mHistoryDataBaiduMapFragment) {
|
||||
// mHistoryDataBaiduMapFragment!!.setPetUserLatLng()
|
||||
mHistoryDataBaiduMapFragment?.apply {
|
||||
mUserLatLng?.let {
|
||||
moveCameraLocation(it)
|
||||
setPetMarkerLatLng(it)
|
||||
}
|
||||
}
|
||||
} else if (null != mHistoryDataGoogleMapFragment) {
|
||||
mHistoryDataGoogleMapFragment?.apply {
|
||||
mUserLatLng?.let {
|
||||
|
||||
@@ -5,7 +5,7 @@ import androidx.fragment.app.Fragment
|
||||
import com.abbidot.baselibrary.util.AppUtils
|
||||
import com.abbidot.tracker.base.BaseMapCommon
|
||||
import com.abbidot.tracker.bean.HistoryDataBean
|
||||
import com.abbidot.tracker.deprecated.ui.fragment.map.baidumap.NavigationBaiduMapFragment
|
||||
import com.abbidot.tracker.ui.fragment.map.baidumap.WiFiZoneBaiduMapFragment
|
||||
import com.abbidot.tracker.ui.fragment.map.googlemap.WiFiZone2GoogleMapFragment
|
||||
|
||||
/**
|
||||
@@ -16,20 +16,20 @@ import com.abbidot.tracker.ui.fragment.map.googlemap.WiFiZone2GoogleMapFragment
|
||||
class WifiZone2MapCommon : BaseMapCommon() {
|
||||
|
||||
private var mWiFiZone2GoogleMapFragment: WiFiZone2GoogleMapFragment? = null
|
||||
private var mBaiduMapFragment: NavigationBaiduMapFragment? = null
|
||||
private var mBaiduMapFragment: WiFiZoneBaiduMapFragment? = null
|
||||
|
||||
fun getMapFragment(context: Context): Fragment {
|
||||
fun getMapFragment(context: Context, firstBind: Boolean): Fragment {
|
||||
return if (AppUtils.isChina(AppUtils.SWITCH_MAP_TYPE)) {
|
||||
mBaiduMapFragment = NavigationBaiduMapFragment.newInstance(context)
|
||||
mBaiduMapFragment = WiFiZoneBaiduMapFragment.newInstance(context)
|
||||
mBaiduMapFragment!!
|
||||
} else {
|
||||
mWiFiZone2GoogleMapFragment = WiFiZone2GoogleMapFragment.newInstance(context)
|
||||
mWiFiZone2GoogleMapFragment = WiFiZone2GoogleMapFragment.newInstance(context, firstBind)
|
||||
mWiFiZone2GoogleMapFragment!!
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshLocation() {
|
||||
mWiFiZone2GoogleMapFragment?.getLastLocation()
|
||||
// mWiFiZone2GoogleMapFragment?.getLastLocation()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,6 +43,9 @@ class WifiZone2MapCommon : BaseMapCommon() {
|
||||
if (null != mWiFiZone2GoogleMapFragment) {
|
||||
if (null !== mWiFiZone2GoogleMapFragment!!.mDecWifiAddressData) return mWiFiZone2GoogleMapFragment!!.mDecWifiAddressData
|
||||
return null
|
||||
} else if (null != mBaiduMapFragment) {
|
||||
if (null !== mBaiduMapFragment!!.mDecWifiAddressData) return mBaiduMapFragment!!.mDecWifiAddressData
|
||||
return null
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.abbidot.baselibrary.constant.EventName
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.eventbus.XEventBus
|
||||
import com.abbidot.baselibrary.util.AppUtils
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
@@ -32,10 +34,7 @@ import com.abbidot.tracker.util.Util.Companion.safeRecycle
|
||||
import com.abbidot.tracker.util.ViewUtil
|
||||
import com.abbidot.tracker.widget.MapMarkerInfoView
|
||||
import com.abbidot.tracker.widget.TypefaceTextView
|
||||
import com.baidu.location.BDAbstractLocationListener
|
||||
import com.baidu.location.BDLocation
|
||||
import com.baidu.location.LocationClient
|
||||
import com.baidu.location.LocationClientOption
|
||||
import com.baidu.mapapi.map.BaiduMap
|
||||
import com.baidu.mapapi.map.BitmapDescriptor
|
||||
import com.baidu.mapapi.map.BitmapDescriptorFactory
|
||||
@@ -54,6 +53,7 @@ import com.baidu.mapapi.map.PolylineOptions
|
||||
import com.baidu.mapapi.map.Stroke
|
||||
import com.baidu.mapapi.map.TextureMapView
|
||||
import com.baidu.mapapi.model.LatLng
|
||||
import com.baidu.mapapi.model.LatLngBounds
|
||||
import com.baidu.mapapi.utils.DistanceUtil
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.abs
|
||||
@@ -74,25 +74,17 @@ abstract class BaseBaiduMapFragment :
|
||||
var isMapLoadOk = false
|
||||
|
||||
//地图放大
|
||||
private var mBaiduMapZoom = 19f
|
||||
private var mBaiduMapZoom = 18.8f
|
||||
|
||||
//自定显示宠物头像地点信息图层
|
||||
protected var mMarker: Overlay? = null
|
||||
|
||||
//宠物大头针设置自定义头像
|
||||
private var mPetHeadIconBitmap: Bitmap? = null
|
||||
|
||||
//宠物头像地址
|
||||
var mPetHeadUrl = ""
|
||||
|
||||
//头像为空,用默认类型的头像
|
||||
private var mPetType = ConstantInt.DogPetType
|
||||
|
||||
//坐标类型,定位SDK默认输出GCJ02坐标,地图SDK默认输出BD09ll坐标。火星GCJ02坐标https://lbsyun.baidu.com/faq/api?title=androidsdk/guide/create-map/location
|
||||
private val mCoordType = "GCJ02"
|
||||
private var mLocationClient: LocationClient? = null
|
||||
private var mLocationListener: BDAbstractLocationListener? = null
|
||||
|
||||
private var mSensorManager: SensorManager? = null
|
||||
private var mSensor: Sensor? = null
|
||||
private var mSensorEventListener: SensorEventListener? = null
|
||||
@@ -132,15 +124,40 @@ abstract class BaseBaiduMapFragment :
|
||||
//自定义精度圈边框颜色
|
||||
setMyLocationConfiguration(locationConfiguration)
|
||||
|
||||
//设置是否允许俯视手势
|
||||
uiSettings.isOverlookingGesturesEnabled = false
|
||||
//设置是否允许抛出惯性手势
|
||||
uiSettings.setFlingEnable(false)
|
||||
//没有宠物位置,默认北京经纬度
|
||||
val lat = MMKVUtil.getDouble(MMKVKey.MapShowDefaultLat)
|
||||
val lon = MMKVUtil.getDouble(MMKVKey.MapShowDefaultLon)
|
||||
if (lat != 0.0 && lon != 0.0) {
|
||||
val status = MapStatusUpdateFactory.newLatLng(getBaiduMapLatLng(lat, lon))
|
||||
setMapStatus(status)
|
||||
}
|
||||
|
||||
uiSettings.let {
|
||||
//设置是否允许俯视手势
|
||||
it.isOverlookingGesturesEnabled = false
|
||||
//设置是否允许抛出惯性手势
|
||||
it.setFlingEnable(false)
|
||||
//指南针为开启状态
|
||||
it.isCompassEnabled = true
|
||||
}
|
||||
|
||||
setOnMapLoadedCallback {
|
||||
LogUtil.e("百度地图加载好了")
|
||||
isMapLoadOk = true
|
||||
|
||||
initMyLocationData()
|
||||
|
||||
XEventBus.observe(viewLifecycleOwner, EventName.LocationData) { loc: BDLocation ->
|
||||
mUserLatLng = LatLng(loc.latitude, loc.longitude)
|
||||
val locData = MyLocationData.Builder().accuracy(loc.radius)
|
||||
// 此处设置开发者获取到的方向信息,顺时针0-360
|
||||
.direction(loc.direction).latitude(loc.latitude).longitude(loc.longitude)
|
||||
.build()
|
||||
// LogUtil.e("百度定位成功返回: ${loc.latitude}, ${loc.longitude}")
|
||||
setMyLocationData(locData)
|
||||
locationSuccess(loc)
|
||||
}
|
||||
|
||||
onMapLoadOk(this)
|
||||
}
|
||||
}
|
||||
@@ -184,6 +201,25 @@ abstract class BaseBaiduMapFragment :
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化用户位置数据
|
||||
*/
|
||||
private fun initMyLocationData() {
|
||||
initSensorEvent(mContext!!)
|
||||
mBaiduMap?.apply {
|
||||
val userGpsLat = MMKVUtil.getDouble(MMKVKey.UserGpsLat)
|
||||
val userGpsLon = MMKVUtil.getDouble(MMKVKey.UserGpsLon)
|
||||
if (userGpsLat != 0.0 || userGpsLon != 0.0) {
|
||||
getBaiduMapLatLng(userGpsLat, userGpsLon).let {
|
||||
val locData =
|
||||
MyLocationData.Builder().latitude(it.latitude).longitude(it.longitude)
|
||||
.build()
|
||||
setMyLocationData(locData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置地图样式
|
||||
*/
|
||||
@@ -223,8 +259,6 @@ abstract class BaseBaiduMapFragment :
|
||||
*/
|
||||
fun setPetHeadIconUrl(petHeadUrl: String) {
|
||||
mPetHeadUrl = petHeadUrl
|
||||
mPetHeadIconBitmap.safeRecycle()
|
||||
mPetHeadIconBitmap = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,6 +283,21 @@ abstract class BaseBaiduMapFragment :
|
||||
mMarker = mBaiduMap!!.addOverlay(option)
|
||||
}
|
||||
|
||||
/**
|
||||
* 由 points 组成的区域 距离手机屏幕距离screenPaddingPx 像素单位
|
||||
*/
|
||||
fun setLatLngZoom(context: Context, vararg points: LatLng) {
|
||||
// val width = context.resources.displayMetrics.widthPixels
|
||||
// val height = context.resources.displayMetrics.heightPixels
|
||||
// val padding = width / 8
|
||||
val builder = LatLngBounds.Builder()
|
||||
for (item in points) {
|
||||
builder.include(toGCJ02LatLon(item))
|
||||
}
|
||||
// bounds 设置显示在屏幕中的地图地理范围
|
||||
mBaiduMap?.setMapStatus(MapStatusUpdateFactory.newLatLngZoom(builder.build(), 10, 0, 10, 0))
|
||||
}
|
||||
|
||||
suspend fun getMarkerBitmapDescriptor(
|
||||
context: Context,
|
||||
headUrl: String,
|
||||
@@ -287,22 +336,71 @@ abstract class BaseBaiduMapFragment :
|
||||
/**
|
||||
* 地图添加图片
|
||||
*/
|
||||
private fun addImageMarker(
|
||||
lat: Double, lon: Double, imageTypeResId: Int, needConvertGCJ02: Boolean = true
|
||||
) {
|
||||
fun addImageMarker(
|
||||
lat: Double,
|
||||
lon: Double,
|
||||
imageTypeResId: Int,
|
||||
needConvertGCJ02: Boolean = true,
|
||||
anchorCenter: Boolean = true,
|
||||
): Overlay? {
|
||||
var overlay: Overlay? = null
|
||||
mBaiduMap?.apply {
|
||||
val latLng = getBaiduMapLatLng(lat, lon, needConvertGCJ02)
|
||||
//构建MarkerOption,用于在地图上添加Marker ,目前支持掉下和生长两种动画
|
||||
val option = getMarkerOptions(lat, lon, imageTypeResId, needConvertGCJ02, anchorCenter)
|
||||
overlay = addOverlay(option)
|
||||
}
|
||||
return overlay
|
||||
}
|
||||
|
||||
val bitmap = ImageUtil.getBitmapFromDrawableAndSvg(mContext!!, imageTypeResId)
|
||||
//构建MarkerOption,用于在地图上添加Marker
|
||||
val option =
|
||||
MarkerOptions().position(latLng).animateType(MarkerOptions.MarkerAnimateType.grow)
|
||||
.icon(BitmapDescriptorFactory.fromBitmap(bitmap)).apply {
|
||||
/**
|
||||
* 获取地图Marker选项
|
||||
* @param anchorCenter 锚点是否需要居中显示,默认(0.5f, 1.0f)水平居中,垂直下对齐,底下居中显示
|
||||
*/
|
||||
fun getMarkerOptions(
|
||||
lat: Double,
|
||||
lon: Double,
|
||||
imageTypeResId: Int,
|
||||
needConvertGCJ02: Boolean = true,
|
||||
anchorCenter: Boolean = false,
|
||||
): MarkerOptions? {
|
||||
var markerOptions: MarkerOptions?
|
||||
//构建MarkerOption,用于在地图上添加Marker ,animateTypes掉下动画
|
||||
val latLng = getBaiduMapLatLng(lat, lon, needConvertGCJ02)
|
||||
val bitmap = ImageUtil.getBitmapFromDrawableAndSvg(mContext!!, imageTypeResId)
|
||||
markerOptions =
|
||||
MarkerOptions().position(latLng).animateType(MarkerOptions.MarkerAnimateType.grow)
|
||||
.icon(BitmapDescriptorFactory.fromBitmap(bitmap)).apply {
|
||||
if (anchorCenter) {
|
||||
anchor(anchorX, anchorY / 2)
|
||||
}
|
||||
addOverlay(option)
|
||||
bitmap?.recycle()
|
||||
}
|
||||
}
|
||||
bitmap?.safeRecycle()
|
||||
return markerOptions
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取地图Marker选项
|
||||
* @param anchorCenter 锚点是否需要居中显示,默认(0.5f, 1.0f)水平居中,垂直下对齐,底下居中显示
|
||||
*/
|
||||
fun getMarkerOptions(
|
||||
latLng: LatLng,
|
||||
imageTypeResId: Int,
|
||||
needConvertGCJ02: Boolean = true,
|
||||
anchorCenter: Boolean = false,
|
||||
): MarkerOptions? {
|
||||
var markerOptions: MarkerOptions?
|
||||
//构建MarkerOption,用于在地图上添加Marker ,animateTypes掉下动画
|
||||
val latLng = getBaiduMapLatLng(latLng.latitude, latLng.longitude, needConvertGCJ02)
|
||||
val bitmap = ImageUtil.getBitmapFromDrawableAndSvg(mContext!!, imageTypeResId)
|
||||
markerOptions =
|
||||
MarkerOptions().position(latLng).animateType(MarkerOptions.MarkerAnimateType.grow)
|
||||
.icon(BitmapDescriptorFactory.fromBitmap(bitmap)).apply {
|
||||
if (anchorCenter) {
|
||||
anchor(anchorX, anchorY / 2)
|
||||
}
|
||||
}
|
||||
bitmap?.safeRecycle()
|
||||
return markerOptions
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -391,7 +489,7 @@ abstract class BaseBaiduMapFragment :
|
||||
/**
|
||||
* 显示信息窗(弹窗覆盖物InfoWindow)
|
||||
*/
|
||||
fun showMarkerInfoWindow(historyDataBean: HistoryDataBean) {
|
||||
fun showMarkerInfoWindow(historyDataBean: HistoryDataBean, offsetY: Int = 0) {
|
||||
historyDataBean.apply {
|
||||
val convertLatLng = getBaiduMapLatLng(latitude, longitude)
|
||||
val view = LayoutInflater.from(mContext).inflate(R.layout.marker_info_contents, null)
|
||||
@@ -400,9 +498,9 @@ abstract class BaseBaiduMapFragment :
|
||||
view.findViewById<TypefaceTextView>(R.id.map_pet_location_update_time)
|
||||
addressTextView.text = address
|
||||
timeTextView.text = dayTime
|
||||
val mInfoWindow = InfoWindow(
|
||||
view, convertLatLng, -(mPetHeadIconBitmap?.width!! + 30)
|
||||
)
|
||||
addressTextView.visibility = if (TextUtils.isEmpty(address)) View.GONE else View.VISIBLE
|
||||
timeTextView.visibility = if (TextUtils.isEmpty(dayTime)) View.GONE else View.VISIBLE
|
||||
val mInfoWindow = InfoWindow(view, convertLatLng, offsetY)
|
||||
mBaiduMap?.showInfoWindow(mInfoWindow)
|
||||
}
|
||||
}
|
||||
@@ -661,9 +759,9 @@ abstract class BaseBaiduMapFragment :
|
||||
//添加起始点图片
|
||||
if (startCapImageRes > 0) {
|
||||
//构建MarkerOption,用于在地图上添加Marker
|
||||
val option = MarkerOptions().position(latLngList[0])
|
||||
.animateType(MarkerOptions.MarkerAnimateType.grow)
|
||||
.icon(BitmapDescriptorFactory.fromResource(startCapImageRes))
|
||||
val option = getMarkerOptions(
|
||||
latLngList[0], startCapImageRes, needConvertGCJ02 = false, anchorCenter = true
|
||||
)
|
||||
//在地图上添加Marker,并显示
|
||||
baiduMap.addOverlay(option)
|
||||
}
|
||||
@@ -685,63 +783,11 @@ abstract class BaseBaiduMapFragment :
|
||||
clearFenceList()
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始定位,请求用户当前的位置
|
||||
*/
|
||||
fun startLocation(locationPeriod: Int = 1, needStopLocation: Boolean = true) {
|
||||
if (null != mLocationClient) return
|
||||
initSensorEvent(mContext!!)
|
||||
//定位初始化
|
||||
mLocationClient = LocationClient(mContext)
|
||||
//通过LocationClientOption设置LocationClient相关参数
|
||||
val option = LocationClientOption()
|
||||
// 打开gps
|
||||
option.openGps = true
|
||||
// 设置坐标类型
|
||||
option.setCoorType(mCoordType)
|
||||
//设置定位刷新间隔
|
||||
option.setScanSpan(locationPeriod * 1000)
|
||||
//设置locationClientOption
|
||||
mLocationClient!!.locOption = option
|
||||
//注册LocationListener监听器
|
||||
mLocationListener = object : BDAbstractLocationListener() {
|
||||
override fun onReceiveLocation(location: BDLocation?) {
|
||||
//mapView 销毁后不在处理新接收的位置
|
||||
if (null == location) {
|
||||
return
|
||||
}
|
||||
val locData = MyLocationData.Builder().accuracy(location.radius)
|
||||
// 此处设置开发者获取到的方向信息,顺时针0-360
|
||||
.direction(location.direction).latitude(location.latitude)
|
||||
.longitude(location.longitude).build()
|
||||
LogUtil.e("百度定位成功: ${location.latitude}, ${location.longitude}")
|
||||
mBaiduMap!!.setMyLocationData(locData)
|
||||
if (needStopLocation) stopLocation()
|
||||
//转换为gps经纬度
|
||||
LonAndLatUtil.convertFromGCJ02ToWGS84(location.latitude, location.longitude).let {
|
||||
MMKVUtil.putDouble(MMKVKey.UserGpsLat, it[0])
|
||||
MMKVUtil.putDouble(MMKVKey.UserGpsLon, it[1])
|
||||
//Android 百度定位 SDK 中,location.getSpeed() 返回的单位是 公里/小时(km/h)。
|
||||
//注意:
|
||||
//只有 GNSS/卫星定位结果通常才有速度信息。
|
||||
//非 GNSS 定位时可能没有有效速度,默认值是 0.0f。
|
||||
//可先用 location.hasSpeed() 判断是否包含速度信息。
|
||||
//保存速度单位是米/秒(m/s)`
|
||||
MMKVUtil.putFloat(MMKVKey.UserGpsSpeed, (location.speed / 3.6f))
|
||||
}
|
||||
mUserLatLng = LatLng(location.latitude, location.longitude)
|
||||
locationSuccess(location)
|
||||
}
|
||||
}
|
||||
mLocationClient!!.registerLocationListener(mLocationListener)
|
||||
//开启定位
|
||||
mLocationClient!!.start()
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置方向感应器,百度地图使用
|
||||
*/
|
||||
private fun initSensorEvent(context: Context) {
|
||||
if (mSensorManager != null) return
|
||||
// 获得传感器管理器
|
||||
mSensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||
if (mSensorManager != null) {
|
||||
@@ -784,16 +830,6 @@ abstract class BaseBaiduMapFragment :
|
||||
mBaiduMap!!.setMyLocationData(myLocData)
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止定位
|
||||
*/
|
||||
private fun stopLocation() {
|
||||
mLocationClient?.apply {
|
||||
unRegisterLocationListener(mLocationListener)
|
||||
stop()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据轨迹获取地图缩放比例
|
||||
*/
|
||||
@@ -959,9 +995,6 @@ abstract class BaseBaiduMapFragment :
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mSensorManager?.unregisterListener(mSensorEventListener)
|
||||
mPetHeadIconBitmap.safeRecycle()
|
||||
mPetHeadIconBitmap = null
|
||||
stopLocation()
|
||||
//在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
|
||||
mMapView.onDestroy()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.abbidot.tracker.ui.fragment.map.baidumap
|
||||
|
||||
import android.content.Context
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.abbidot.tracker.bean.WiFiZoneBean
|
||||
import com.baidu.mapapi.map.BaiduMap
|
||||
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass.
|
||||
* Use the [EditWiFiZoneBaiduFragment.newInstance] factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
class EditWiFiZoneBaiduFragment : BaseBaiduMapFragment() {
|
||||
|
||||
private var mMapLoadOk: (() -> Unit)? = null
|
||||
private var mWiFiZoneBean: WiFiZoneBean? = null
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newInstance(context: Context, wiFiZoneBean: WiFiZoneBean, mapLoadOk: () -> Unit) =
|
||||
EditWiFiZoneBaiduFragment().apply {
|
||||
mContext = context
|
||||
mMapLoadOk = mapLoadOk
|
||||
mWiFiZoneBean = wiFiZoneBean
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMapLoadOk(baiduMap: BaiduMap) {
|
||||
mMapLoadOk?.invoke()
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.baselibrary.util.Utils
|
||||
import com.abbidot.tracker.bean.FencesBean
|
||||
import com.abbidot.tracker.constant.ConstantInt
|
||||
import com.abbidot.tracker.ui.common.map.FencesAddEditMapCommon
|
||||
@@ -19,6 +18,7 @@ import com.baidu.location.BDLocation
|
||||
import com.baidu.mapapi.map.BaiduMap
|
||||
import com.baidu.mapapi.map.MapStatus
|
||||
import com.baidu.mapapi.model.LatLng
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.pow
|
||||
|
||||
/**
|
||||
@@ -37,6 +37,8 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
|
||||
private lateinit var mMapLoadOk: () -> Unit
|
||||
|
||||
private var isFirst = false
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newInstance(
|
||||
@@ -66,7 +68,6 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
|
||||
setOnMapLongClickListener {
|
||||
resetFencesViewCentre(it)
|
||||
mapOkAndDistancePointLatLng(10)
|
||||
}
|
||||
|
||||
setOnMapGestureListener(object : BaiduMap.onMapGestureListener {
|
||||
@@ -85,35 +86,27 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
override fun onMapDoubleTouch(p0: Point?, p1: MapStatus?): Boolean {
|
||||
//双击放大
|
||||
LogUtil.e("onMapDoubleTouch")
|
||||
isRecoverFencesView = true
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMapTwoClick(p0: Point?, p1: Point?, p2: MapStatus?): Boolean {
|
||||
//双指点击缩小
|
||||
LogUtil.e("onMapTwoClick")
|
||||
isRecoverFencesView = true
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMapKneading(p0: Point?, p1: Point?, p2: MapStatus?): Boolean {
|
||||
LogUtil.e("onMapKneading")
|
||||
//监听地图放大缩小操作
|
||||
if (getBaiduMapZoom() != mapStatus.zoom) {
|
||||
setBaiduMapZoom(mapStatus.zoom)
|
||||
resetFencesViewSize()
|
||||
|
||||
mFencesBean.let {
|
||||
resetFencesViewCentre(
|
||||
getBaiduMapLatLng(
|
||||
it.latitudeCenter, it.longitudeCenter
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
recoverFencesView()
|
||||
isRecoverFencesView = true
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMapOverLooking(p0: Point?, p1: Point?, p2: MapStatus?): Boolean {
|
||||
LogUtil.e("onMapOverLooking")
|
||||
isRecoverFencesView = true
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -127,16 +120,42 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
|
||||
override fun onMapStatusChangeFinish(p0: MapStatus?) {
|
||||
LogUtil.e("onMapStatusChangeFinish")
|
||||
if (isRecoverFencesView) {
|
||||
isRecoverFencesView = false
|
||||
recoverFencesView()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
startLocation()
|
||||
|
||||
//变量是否初始化
|
||||
if (::mMapLoadOk.isInitialized) mMapLoadOk()
|
||||
}
|
||||
|
||||
private var isRecoverFencesView = false
|
||||
|
||||
/**
|
||||
* 恢复围栏视图大小
|
||||
*/
|
||||
private fun recoverFencesView() {
|
||||
mBaiduMap?.apply {
|
||||
//监听地图放大缩小操作
|
||||
if (getBaiduMapZoom() != mapStatus.zoom) {
|
||||
setBaiduMapZoom(mapStatus.zoom)
|
||||
resetFencesViewSize()
|
||||
setScaleLimitDistance()
|
||||
|
||||
mFencesBean.let {
|
||||
resetFencesViewCentre(
|
||||
getBaiduMapLatLng(
|
||||
it.latitudeCenter, it.longitudeCenter
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun locationSuccess(location: BDLocation?) {
|
||||
if (isEditFences) {
|
||||
mFencesBean.apply {
|
||||
@@ -169,11 +188,22 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
* 地图准备好计算距离
|
||||
*/
|
||||
fun mapOkAndDistancePointLatLng(delayMillis: Long = 500) {
|
||||
if (mFencesBean.startDrag) return
|
||||
//延时计算距离,防止围栏没画好/地图摄像头移动中
|
||||
mFencesCircleView.postDelayed({
|
||||
if (delayMillis == 0L) {
|
||||
val arrayOfDistance = getLatLngAndCalDistance()
|
||||
mOnActivityCallBack?.calculationDistance(arrayOfDistance)
|
||||
}, delayMillis)
|
||||
} else {
|
||||
//延时计算距离,防止围栏没画好/地图摄像头移动中
|
||||
mFencesCircleView.postDelayed({
|
||||
val arrayOfDistance = getLatLngAndCalDistance()
|
||||
mOnActivityCallBack?.calculationDistance(arrayOfDistance)
|
||||
if (!isFirst) {
|
||||
isFirst = true
|
||||
setScaleLimitDistance()
|
||||
}
|
||||
}, delayMillis)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,20 +211,25 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
*/
|
||||
private fun restoreEditFences() {
|
||||
var arrayOfDistance = arrayOf("0")
|
||||
setScaleLimitDistance()
|
||||
mFencesBean.apply {
|
||||
when (mFencesBean.fenceShapeType) {
|
||||
ConstantInt.CircleShapeType -> {
|
||||
val radiusPx = getCircleRadiusPx(radius.toDouble())
|
||||
mFencesCircleView.let {
|
||||
it.visibility = View.VISIBLE
|
||||
it.setCircleRadiusPx(radiusPx.toFloat())
|
||||
arrayOfDistance = arrayOf("$radius")
|
||||
}
|
||||
restoreCircleFences()
|
||||
val showDistance = Util.getShowDistance(radius)
|
||||
arrayOfDistance = arrayOf("$radius", "$showDistance")
|
||||
}
|
||||
|
||||
ConstantInt.RectangleShapeType -> {
|
||||
restoreRectFences()
|
||||
arrayOfDistance = arrayOf("$longDistance", "$shortDistance")
|
||||
val showWidthDistance = Util.getShowDistance(longDistance)
|
||||
val showHeightDistance = Util.getShowDistance(shortDistance)
|
||||
arrayOfDistance = arrayOf(
|
||||
"$longDistance",
|
||||
"$shortDistance",
|
||||
"$showWidthDistance",
|
||||
"$showHeightDistance"
|
||||
)
|
||||
}
|
||||
|
||||
ConstantInt.PolygonShapeType -> {
|
||||
@@ -212,13 +247,9 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
*/
|
||||
fun resetFencesViewCentre(centreLatLng: LatLng) {
|
||||
mBaiduMap?.projection?.toScreenLocation(centreLatLng)?.apply {
|
||||
if (mFencesCircleView.isVisible) {
|
||||
mFencesCircleView.setCentreXY(this)
|
||||
} else if (mFencesRectView.isVisible) {
|
||||
mFencesRectView.setCentreXY(this)
|
||||
} else if (mFencesPolygonView.isVisible) {
|
||||
mFencesPolygonView.setCentreXY(this)
|
||||
}
|
||||
mFencesCircleView.setCentreXY(this)
|
||||
mFencesRectView.setCentreXY(this)
|
||||
mFencesPolygonView.setCentreXY(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,8 +259,9 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
private fun resetFencesViewSize() {
|
||||
if (mFencesCircleView.isVisible) {
|
||||
if (mFencesBean.radius <= 0.0) return
|
||||
val radiusPx = zoomToCircleRadiusPx(mFencesBean.radius.toDouble())
|
||||
mFencesCircleView.setCircleRadiusPx(radiusPx.toFloat())
|
||||
// val radiusPx = zoomToCircleRadiusPx(mFencesBean.radius.toDouble())
|
||||
// mFencesCircleView.setCircleRadiusPx(radiusPx.toFloat())
|
||||
restoreCircleFences()
|
||||
} else if (mFencesRectView.isVisible) {
|
||||
restoreRectFences()
|
||||
} else if (mFencesPolygonView.isVisible) {
|
||||
@@ -237,35 +269,85 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置围栏最小可拖动距离
|
||||
*/
|
||||
private fun setScaleLimitDistance() {
|
||||
mBaiduMap?.apply {
|
||||
//假设取个离(100,100)x坐标100的点
|
||||
var stepX: Int
|
||||
var stepY: Int
|
||||
//手机坐标点转换为经纬度
|
||||
val centreLatLng = Point(100, 100).let {
|
||||
stepX = it.x + 100
|
||||
stepY = it.y
|
||||
projection.fromScreenLocation(it)
|
||||
}
|
||||
val stepLatLng = projection.fromScreenLocation(Point(stepX, stepY))
|
||||
val stepDistance = Util.measureLatLonDistance(
|
||||
centreLatLng.latitude,
|
||||
centreLatLng.longitude,
|
||||
stepLatLng.latitude,
|
||||
stepLatLng.longitude
|
||||
)
|
||||
//限制圆半径50m
|
||||
val limitRadius = 100 / stepDistance * 50
|
||||
//限制矩形边长100m
|
||||
val limitSide = 100 / stepDistance * 100
|
||||
LogUtil.e("scaleLimitDistance,$stepDistance,$limitRadius,$limitSide,${mapStatus.zoom}")
|
||||
mFencesCircleView.mLimitRadius = limitRadius.toFloat()
|
||||
mFencesRectView.mLimitSide = limitSide.toFloat()
|
||||
mFencesPolygonView.mLimitSide = limitSide.toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回2种距离,第一个是设备使用真实距离,第二个是界面显示10的倍数距离
|
||||
*/
|
||||
private fun getLatLngAndCalDistance(): Array<String> {
|
||||
// 经纬度转换为手机坐标点
|
||||
// val x = mBaiduMap!!.projection.toScreenLocation(it).x
|
||||
if (null == mBaiduMap) return arrayOf("0", "0")
|
||||
return when (mFencesBean.fenceShapeType) {
|
||||
ConstantInt.CircleShapeType -> {
|
||||
//手机坐标点转换为经纬度
|
||||
val centreLatLng = mFencesCircleView.getCircleCentrePoint()
|
||||
.let { mBaiduMap!!.projection.fromScreenLocation(it) }
|
||||
val startLatLng = mFencesCircleView.getCircleLineStartPoint()
|
||||
.let { mBaiduMap!!.projection.fromScreenLocation(it) }
|
||||
val endLatLng = mFencesCircleView.getCircleLineEndPoint()
|
||||
.let { mBaiduMap!!.projection.fromScreenLocation(it) }
|
||||
// mEndLatLng = endLatLng
|
||||
LogUtil.e("mBaiduMap,getLatLngAndCalDistance 监听回调")
|
||||
LogUtil.e("startLatLng=$centreLatLng,endLatLng=$endLatLng")
|
||||
// LogUtil.e("startLatLng=$centreLatLng,endLatLng=$endLatLng")
|
||||
val distance = Util.measureLatLonDistance(
|
||||
centreLatLng.latitude,
|
||||
centreLatLng.longitude,
|
||||
startLatLng.latitude,
|
||||
startLatLng.longitude,
|
||||
endLatLng.latitude,
|
||||
endLatLng.longitude
|
||||
)
|
||||
val distanceInt = distance.toInt()
|
||||
val showDistance = Util.getShowDistance(distanceInt)
|
||||
//把输出的GCJ02坐标转换为gps原生坐标WGS84
|
||||
val gpsWGS84 = LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
centreLatLng.latitude, centreLatLng.longitude
|
||||
)
|
||||
mFencesBean.apply {
|
||||
latitudeCenter = gpsWGS84[0]
|
||||
longitudeCenter = gpsWGS84[1]
|
||||
LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
centreLatLng.latitude, centreLatLng.longitude
|
||||
).let {
|
||||
latitudeCenter = it[0]
|
||||
longitudeCenter = it[1]
|
||||
}
|
||||
LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
startLatLng.latitude, startLatLng.longitude
|
||||
).let {
|
||||
ancillaryOtherLatitude = it[0]
|
||||
ancillaryOtherLongitude = it[1]
|
||||
}
|
||||
LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
endLatLng.latitude, endLatLng.longitude
|
||||
).let {
|
||||
ancillaryLatitude = it[0]
|
||||
ancillaryLongitude = it[1]
|
||||
}
|
||||
}
|
||||
arrayOf(
|
||||
Utils.formatDecimal(distance, 2)
|
||||
distanceInt.toString(), showDistance.toString()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -296,39 +378,50 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
rectCLatLng.latitude,
|
||||
rectCLatLng.longitude
|
||||
)
|
||||
val widthDistance = rectWidthDistance.toInt()
|
||||
val showWidthDistance = Util.getShowDistance(widthDistance)
|
||||
val heightDistance = rectHeightDistance.toInt()
|
||||
val showHeightDistance = Util.getShowDistance(heightDistance)
|
||||
|
||||
//把输出的GCJ02坐标转换为gps原生坐标WGS84
|
||||
val centreGpsWGS84 = LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
centreLatLng.latitude, centreLatLng.longitude
|
||||
)
|
||||
val rectAGpsWGS84 = LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
rectALatLng.latitude, rectALatLng.longitude
|
||||
)
|
||||
val rectBGpsWGS84 = LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
rectBLatLng.latitude, rectBLatLng.longitude
|
||||
)
|
||||
val rectCGpsWGS84 = LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
rectCLatLng.latitude, rectCLatLng.longitude
|
||||
)
|
||||
val rectDGpsWGS84 = LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
rectDLatLng.latitude, rectDLatLng.longitude
|
||||
)
|
||||
mFencesBean.apply {
|
||||
latitudeCenter = centreGpsWGS84[0]
|
||||
longitudeCenter = centreGpsWGS84[1]
|
||||
latitudeA = rectAGpsWGS84[0]
|
||||
longitudeA = rectAGpsWGS84[1]
|
||||
latitudeB = rectBGpsWGS84[0]
|
||||
longitudeB = rectBGpsWGS84[1]
|
||||
latitudeC = rectCGpsWGS84[0]
|
||||
longitudeC = rectCGpsWGS84[1]
|
||||
latitudeD = rectDGpsWGS84[0]
|
||||
longitudeD = rectDGpsWGS84[1]
|
||||
LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
centreLatLng.latitude, centreLatLng.longitude
|
||||
).let {
|
||||
latitudeCenter = it[0]
|
||||
longitudeCenter = it[1]
|
||||
}
|
||||
LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
rectALatLng.latitude, rectALatLng.longitude
|
||||
).let {
|
||||
latitudeA = it[0]
|
||||
longitudeA = it[1]
|
||||
}
|
||||
LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
rectBLatLng.latitude, rectBLatLng.longitude
|
||||
).let {
|
||||
latitudeB = it[0]
|
||||
longitudeB = it[1]
|
||||
}
|
||||
LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
rectCLatLng.latitude, rectCLatLng.longitude
|
||||
).let {
|
||||
latitudeC = it[0]
|
||||
longitudeC = it[1]
|
||||
}
|
||||
LonAndLatUtil.convertFromGCJ02ToWGS84(
|
||||
rectDLatLng.latitude, rectDLatLng.longitude
|
||||
).let {
|
||||
latitudeD = it[0]
|
||||
longitudeD = it[1]
|
||||
}
|
||||
}
|
||||
//长度和高度
|
||||
arrayOf(
|
||||
Utils.formatDecimal(rectWidthDistance, 2),
|
||||
Utils.formatDecimal(rectHeightDistance, 2)
|
||||
widthDistance.toString(),
|
||||
heightDistance.toString(),
|
||||
showWidthDistance.toString(),
|
||||
showHeightDistance.toString()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -404,10 +497,59 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 还原圆形围栏
|
||||
*/
|
||||
private fun restoreCircleFences() {
|
||||
if (null == mBaiduMap) return
|
||||
mFencesBean.apply {
|
||||
mFencesCircleView.let {
|
||||
it.visibility = View.VISIBLE
|
||||
val pointCentre = mBaiduMap!!.projection.toScreenLocation(
|
||||
getBaiduMapLatLng(
|
||||
latitudeCenter, longitudeCenter
|
||||
)
|
||||
)
|
||||
val pointLineEnd = mBaiduMap!!.projection.toScreenLocation(
|
||||
getBaiduMapLatLng(
|
||||
ancillaryLatitude, ancillaryLongitude
|
||||
)
|
||||
)
|
||||
val radius = abs(pointLineEnd.x - pointCentre.x).toFloat()
|
||||
it.setCircleRadiusPx(radius)
|
||||
|
||||
//圆形大小变了,其他形状的围栏也要改变大小
|
||||
val rectA = Point(
|
||||
(pointLineEnd.x - radius * 2).toInt(), (pointLineEnd.y - radius).toInt()
|
||||
)
|
||||
val rectB = Point(pointLineEnd.x, (pointLineEnd.y - radius).toInt())
|
||||
val rectC = Point(pointLineEnd.x, (pointLineEnd.y + radius).toInt())
|
||||
val rectD =
|
||||
Point((pointLineEnd.x - radius * 2).toInt(), (pointLineEnd.y + radius).toInt())
|
||||
mFencesRectView.setRectABCDXYPoint(pointCentre, rectA, rectB, rectC, rectD)
|
||||
val polygonA = Point(pointCentre.x, (pointCentre.y - radius).toInt())
|
||||
val polygonB = Point(pointLineEnd.x, (pointLineEnd.y - radius / 2).toInt())
|
||||
val polygonC = Point(pointLineEnd.x, (pointLineEnd.y + radius / 2).toInt())
|
||||
val polygonD = Point(pointCentre.x, (pointCentre.y + radius).toInt())
|
||||
val polygonE = Point(
|
||||
(pointLineEnd.x - 2 * radius).toInt(), (pointLineEnd.y + radius / 2).toInt()
|
||||
)
|
||||
val polygonF = Point(
|
||||
(pointLineEnd.x - 2 * radius).toInt(), (pointLineEnd.y - radius / 2).toInt()
|
||||
)
|
||||
mFencesPolygonView.setPolygonABCDEFPoint(
|
||||
pointCentre, polygonA, polygonB, polygonC, polygonD, polygonE, polygonF
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 还原矩形围栏大小
|
||||
*/
|
||||
private fun restoreRectFences() {
|
||||
if (null == mBaiduMap) return
|
||||
mFencesBean.apply {
|
||||
mFencesRectView.let {
|
||||
it.visibility = View.VISIBLE
|
||||
@@ -426,8 +568,25 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
val pointD = toScreenLocation(
|
||||
getBaiduMapLatLng(latitudeD, longitudeD)
|
||||
)
|
||||
it.setRectABCDXYPoint(
|
||||
pointCentre, pointA, pointB, pointC, pointD
|
||||
it.setRectABCDXYPoint(pointCentre, pointA, pointB, pointC, pointD)
|
||||
|
||||
//矩形大小变了,其他形状的围栏也要改变大小
|
||||
val radius = abs(pointA.x - pointCentre.x).toFloat()
|
||||
mFencesCircleView.setCircleRadiusPx(radius)
|
||||
val minX = minOf(pointA.x, pointB.x, pointC.x, pointD.x)
|
||||
val maxX = maxOf(pointA.x, pointB.x, pointC.x, pointD.x)
|
||||
val minY = minOf(pointA.y, pointB.y, pointC.y, pointD.y)
|
||||
val maxY = maxOf(pointA.y, pointB.y, pointC.y, pointD.y)
|
||||
val difX = maxX - minX
|
||||
val difY = maxY - minY
|
||||
val polygonA = Point(minX + difX / 2, minY)
|
||||
val polygonB = Point(maxX, minY + difY / 4)
|
||||
val polygonC = Point(maxX, maxY - difY / 4)
|
||||
val polygonD = Point(minX + difX / 2, maxY)
|
||||
val polygonE = Point(minX, maxY - difY / 4)
|
||||
val polygonF = Point(minX, minY + difY / 4)
|
||||
mFencesPolygonView.setPolygonABCDEFPoint(
|
||||
pointCentre, polygonA, polygonB, polygonC, polygonD, polygonE, polygonF
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -438,6 +597,7 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
* 还原多边形围栏大小
|
||||
*/
|
||||
private fun restorePolygonFences() {
|
||||
if (null == mBaiduMap) return
|
||||
mFencesBean.apply {
|
||||
mFencesPolygonView.let {
|
||||
it.visibility = View.VISIBLE
|
||||
@@ -465,6 +625,19 @@ class FencesAddEditBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
it.setPolygonABCDEFPoint(
|
||||
pointCentre, pointA, pointB, pointC, pointD, pointE, pointF
|
||||
)
|
||||
|
||||
val maxX = maxOf(pointA.x, pointB.x, pointC.x, pointD.x, pointE.x, pointF.x)
|
||||
//多边形大小变了,其他形状的围栏也要改变大小
|
||||
val radius = abs(maxX - pointCentre.x).toFloat()
|
||||
mFencesCircleView.setCircleRadiusPx(radius)
|
||||
val minX = minOf(pointA.x, pointB.x, pointC.x, pointD.x, pointE.x, pointF.x)
|
||||
val minY = minOf(pointA.y, pointB.y, pointC.y, pointD.y, pointE.y, pointF.y)
|
||||
val maxY = maxOf(pointA.y, pointB.y, pointC.y, pointD.y, pointE.y, pointF.y)
|
||||
val rectA = Point(minX, minY)
|
||||
val rectB = Point(maxX, minY)
|
||||
val rectC = Point(maxX, maxY)
|
||||
val rectD = Point(minX, maxY)
|
||||
mFencesRectView.setRectABCDXYPoint(pointCentre, rectA, rectB, rectC, rectD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,6 @@ class HistoryDataBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
}
|
||||
|
||||
override fun onMapLoadOk(baiduMap: BaiduMap) {
|
||||
//点击地图任意地方都不消失自定义头部地点布局
|
||||
// startLocation(60, false)
|
||||
|
||||
baiduMap.apply {
|
||||
@@ -176,6 +175,7 @@ class HistoryDataBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
val zoom = getDistanceZoom(LatLng(minLat, minLon), LatLng(maxLat, maxLon))
|
||||
LogUtil.e("百度地图zoom==$zoom")
|
||||
setBaiduMapZoom(zoom + 1)
|
||||
// setLatLngZoom(mContext!!, LatLng(minLat, minLon), LatLng(maxLat, maxLon))
|
||||
|
||||
val maxIndex = data.size - 1
|
||||
mCurLatLng = mLatLngList[maxIndex]
|
||||
@@ -321,14 +321,15 @@ class HistoryDataBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
* 设置宠物Marker经纬度
|
||||
*/
|
||||
fun setPetMarkerLatLng(latLng: LatLng) {
|
||||
mBaiduMap?.apply {
|
||||
//显示最上面,层级最高,默认值 0f
|
||||
mBaiduMap?.let { baidu ->
|
||||
mMarkerOptions?.let {
|
||||
it.position(latLng)
|
||||
mMarker?.remove()
|
||||
mMarker = addOverlay(it)
|
||||
mMarker = baidu.addOverlay(it).apply {
|
||||
//显示最上面,层级最高,默认值 0f
|
||||
zIndex = 99
|
||||
}
|
||||
}
|
||||
// setUserMarker()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,7 +152,6 @@ class HomeMapBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
}
|
||||
|
||||
override fun onMapLoadOk(baiduMap: BaiduMap) {
|
||||
startLocation(60, false)
|
||||
|
||||
mBaiduMap?.apply {
|
||||
setOnMarkerClickListener { marker ->
|
||||
|
||||
@@ -23,7 +23,6 @@ class PreviewFencesBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
}
|
||||
|
||||
override fun onMapLoadOk(baiduMap: BaiduMap) {
|
||||
startLocation()
|
||||
//变量是否初始化
|
||||
if (::mMapLoadOk.isInitialized) mMapLoadOk()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
package com.abbidot.tracker.ui.fragment.map.baidumap
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Point
|
||||
import android.view.MotionEvent
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.abbidot.baselibrary.util.AppUtils
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.bean.HistoryDataBean
|
||||
import com.abbidot.tracker.util.LonAndLatUtil
|
||||
import com.abbidot.tracker.vm.GeoCoderViewModel
|
||||
import com.baidu.location.BDLocation
|
||||
import com.baidu.mapapi.map.BaiduMap
|
||||
import com.baidu.mapapi.map.MapStatus
|
||||
import com.baidu.mapapi.map.MarkerOptions
|
||||
import com.baidu.mapapi.model.LatLng
|
||||
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass.
|
||||
* Use the [WiFiZoneBaiduMapFragment.newInstance] factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
class WiFiZoneBaiduMapFragment : BaseBaiduMapFragment() {
|
||||
|
||||
private val mGeoCoderViewModel: GeoCoderViewModel by viewModels()
|
||||
|
||||
//wifi zone当前位置信息 //保存地理信息,方便传参给其他页面
|
||||
var mDecWifiAddressData: HistoryDataBean? = null
|
||||
private var mMarkerOptions: MarkerOptions? = null
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newInstance(context: Context) = WiFiZoneBaiduMapFragment().apply {
|
||||
mContext = context
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMapLoadOk(baiduMap: BaiduMap) {
|
||||
mDecWifiAddressData = HistoryDataBean()
|
||||
|
||||
baiduMap.apply {
|
||||
//是否双击放大当前地图中心点 默认:false 即按照双击位置放大地图
|
||||
uiSettings.setEnlargeCenterWithDoubleClickEnable(true)
|
||||
setOnMapStatusChangeListener(object : BaiduMap.OnMapStatusChangeListener {
|
||||
override fun onMapStatusChangeStart(p0: MapStatus?) {
|
||||
LogUtil.e("onMapStatusChangeStart")
|
||||
mBaiduMap?.hideInfoWindow()
|
||||
}
|
||||
|
||||
override fun onMapStatusChangeStart(p: MapStatus?, p1: Int) {
|
||||
p?.let {
|
||||
getCameraCenterLatLng()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMapStatusChange(p: MapStatus?) {
|
||||
LogUtil.e("onMapStatusChange")
|
||||
p?.let {
|
||||
getCameraCenterLatLng()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMapStatusChangeFinish(p: MapStatus?) {
|
||||
LogUtil.e("setOnMapStatusChangeListener,onMapStatusChangeFinish")
|
||||
p?.let {
|
||||
getCameraCenterLatLng(true)
|
||||
}
|
||||
}
|
||||
})
|
||||
setOnMapGestureListener(object : BaiduMap.onMapGestureListener {
|
||||
override fun onMapScroll(p0: Point?, p1: Point?, p: MapStatus?): Boolean {
|
||||
//平移
|
||||
p?.let {
|
||||
getCameraCenterLatLng()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMapDoubleTouch(p0: Point?, p: MapStatus?): Boolean {
|
||||
//双击放大
|
||||
LogUtil.e("onMapDoubleTouch")
|
||||
p?.let {
|
||||
getCameraCenterLatLng()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMapTwoClick(p0: Point?, p1: Point?, p: MapStatus?): Boolean {
|
||||
//双指点击缩小
|
||||
LogUtil.e("onMapTwoClick")
|
||||
p?.let {
|
||||
getCameraCenterLatLng()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMapKneading(p0: Point?, p1: Point?, p: MapStatus?): Boolean {
|
||||
LogUtil.e("onMapKneading")
|
||||
// p?.let {
|
||||
// getCameraCenterLatLng()
|
||||
// }
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMapOverLooking(p0: Point?, p1: Point?, p2: MapStatus?): Boolean {
|
||||
LogUtil.e("onMapOverLooking")
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMapFling(
|
||||
p0: MotionEvent?, p1: Float, p2: Float, p3: MapStatus?
|
||||
): Boolean {
|
||||
//惯性抛出手势
|
||||
LogUtil.e("onMapFling1")
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMapStatusChangeFinish(p: MapStatus?) {
|
||||
LogUtil.e("onMapStatusChangeFinish")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun liveDataObserve() {
|
||||
//反地理编码成功返回
|
||||
mGeoCoderViewModel.mLatLonAddressLiveData.observe(viewLifecycleOwner) {
|
||||
mDecWifiAddressData?.let { history ->
|
||||
//更新位置时间
|
||||
// history.dayTime = timeString
|
||||
//详细位置
|
||||
history.address = it
|
||||
//传递位置信息给InfoWindowAdapter窗口
|
||||
mMarkerOptions?.let { m ->
|
||||
showMarkerInfoWindow(history, -m.icon.bitmap.height - AppUtils.dpToPx(2))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCameraCenterLatLng(isNeedGeoCoder: Boolean = false) {
|
||||
mBaiduMap?.apply {
|
||||
//地图操作中心点在屏幕中的坐标
|
||||
val latLng = mapStatus.target
|
||||
mMarker?.remove()
|
||||
mMarkerOptions?.let {
|
||||
it.position(latLng)
|
||||
mMarker = addOverlay(it)
|
||||
}
|
||||
if (isNeedGeoCoder) {
|
||||
val gpsLatLng =
|
||||
LonAndLatUtil.convertFromGCJ02ToWGS84(latLng.latitude, latLng.longitude)
|
||||
geoCoderLatLon(gpsLatLng[0], gpsLatLng[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun geoCoderLatLon(latitude: Double, longitude: Double) {
|
||||
mDecWifiAddressData?.apply {
|
||||
this.latitude = latitude
|
||||
this.longitude = longitude
|
||||
}
|
||||
mGeoCoderViewModel.getLatLonAddress(latitude, longitude, false)
|
||||
}
|
||||
|
||||
override fun locationSuccess(location: BDLocation?) {
|
||||
location?.apply {
|
||||
moveCameraLocation(LatLng(latitude, longitude))
|
||||
val gpsLatLng = LonAndLatUtil.convertFromGCJ02ToWGS84(latitude, longitude)
|
||||
if (null == mMarker) {
|
||||
mMarkerOptions = getMarkerOptions(
|
||||
gpsLatLng[0], gpsLatLng[1], R.drawable.icon_location_svg
|
||||
)
|
||||
mMarker = mBaiduMap?.addOverlay(mMarkerOptions)
|
||||
} else mMarker?.remove()
|
||||
geoCoderLatLon(gpsLatLng[0], gpsLatLng[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.abbidot.tracker.ui.fragment.map.googlemap
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Point
|
||||
import android.location.Location
|
||||
import android.os.Bundle
|
||||
@@ -14,7 +12,9 @@ import android.view.ViewGroup
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.abbidot.baselibrary.constant.EventName
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.eventbus.XEventBus
|
||||
import com.abbidot.baselibrary.util.AppUtils
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
@@ -28,13 +28,9 @@ import com.abbidot.tracker.databinding.FragmentGoogleMapBinding
|
||||
import com.abbidot.tracker.util.ImageUtil
|
||||
import com.abbidot.tracker.util.LonAndLatUtil
|
||||
import com.abbidot.tracker.util.Util
|
||||
import com.abbidot.tracker.util.Util.Companion.safeRecycle
|
||||
import com.abbidot.tracker.util.ViewUtil
|
||||
import com.abbidot.tracker.widget.MapDeviceNetView
|
||||
import com.abbidot.tracker.widget.MapMarkerInfoView
|
||||
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.maps.CameraUpdate
|
||||
import com.google.android.gms.maps.CameraUpdateFactory
|
||||
import com.google.android.gms.maps.GoogleMap
|
||||
@@ -59,8 +55,6 @@ import com.google.android.gms.maps.model.PolygonOptions
|
||||
import com.google.android.gms.maps.model.Polyline
|
||||
import com.google.android.gms.maps.model.PolylineOptions
|
||||
import com.google.android.gms.maps.model.RoundCap
|
||||
import com.google.android.gms.tasks.CancellationTokenSource
|
||||
import com.google.android.gms.tasks.Task
|
||||
import com.qmuiteam.qmui.util.QMUIDisplayHelper
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -97,9 +91,6 @@ abstract class BaseGoogleMapFragment :
|
||||
//自定显示用户地点信息图层
|
||||
private var mUserMarker: Marker? = null
|
||||
|
||||
//宠物大头针设置自定义头像
|
||||
private var mPetHeadIconBitmap: Bitmap? = null
|
||||
|
||||
private var mMarkerInfoWindowAdapter: MarkerInfoWindowAdapter? = null
|
||||
|
||||
//宠物头像地址
|
||||
@@ -135,7 +126,7 @@ abstract class BaseGoogleMapFragment :
|
||||
//指定地图的初始照相机位置(指定 null 以使用 默认摄像机位置)
|
||||
val options = GoogleMapOptions().apply {
|
||||
// val options = GoogleMapOptions().liteMode(true)
|
||||
//默认华盛顿经纬度
|
||||
//没有宠物位置,默认华盛顿经纬度
|
||||
val lat = MMKVUtil.getDouble(MMKVKey.MapShowDefaultLat, 38.913611)
|
||||
val lon = MMKVUtil.getDouble(MMKVKey.MapShowDefaultLon, -77.013222)
|
||||
//不使用地图摄像头移动动画,默认级别一样大
|
||||
@@ -184,6 +175,68 @@ abstract class BaseGoogleMapFragment :
|
||||
mGoogleMapView?.onSaveInstanceState(mapViewBundle)
|
||||
}
|
||||
|
||||
override fun onMapReady(googleMap: GoogleMap) {
|
||||
LogUtil.e("谷歌地图加载好了")
|
||||
mGoogleMap = googleMap
|
||||
|
||||
isMapLoadOk = true
|
||||
|
||||
// googleMap.uiSettings.apply {
|
||||
// //右下角工具栏不显示
|
||||
// isMapToolbarEnabled = true
|
||||
// //指南针
|
||||
// isCompassEnabled = true
|
||||
// //定位按钮
|
||||
// isMyLocationButtonEnabled = true
|
||||
// }
|
||||
|
||||
//地图样式
|
||||
setGoogleMapType()
|
||||
|
||||
googleMap.apply {
|
||||
//显示实时交通信息
|
||||
// isTrafficEnabled = true
|
||||
//检测权限,开启用户的当前位置https://developers.google.cn/maps/documentation/android-sdk/location?hl=zh-cn
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
mContext!!, Manifest.permission.ACCESS_FINE_LOCATION
|
||||
) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
|
||||
mContext!!, Manifest.permission.ACCESS_COARSE_LOCATION
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
//启用“我的位置”图层。
|
||||
isMyLocationEnabled = true
|
||||
}
|
||||
uiSettings.let {
|
||||
//禁止显示“我的位置”按钮。
|
||||
it.isMyLocationButtonEnabled = false
|
||||
//用于设置是启用还是停用倾斜手势的偏好设置。
|
||||
// https://developers.google.cn/maps/documentation/android-sdk/reference/com/google/android/libraries/maps/UiSettings?hl=zh-cn
|
||||
it.isMapToolbarEnabled = false
|
||||
it.isTiltGesturesEnabled = false
|
||||
it.isCompassEnabled = true
|
||||
}
|
||||
|
||||
|
||||
XEventBus.observe(viewLifecycleOwner, EventName.LocationData) { loc: Location ->
|
||||
setUserLocationData(loc.latitude, loc.longitude)
|
||||
locationSuccess(loc)
|
||||
}
|
||||
|
||||
val userGpsLat = MMKVUtil.getDouble(MMKVKey.UserGpsLat)
|
||||
val userGpsLon = MMKVUtil.getDouble(MMKVKey.UserGpsLon)
|
||||
if (userGpsLat != 0.0 || userGpsLon != 0.0) {
|
||||
setUserLocationData(userGpsLat, userGpsLon)
|
||||
}
|
||||
|
||||
onMapLoadOk(googleMap)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUserLocationData(lat: Double, lon: Double) {
|
||||
mUserLatLng = LatLng(lat, lon)
|
||||
setUserMarker()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mGoogleMapView?.onPause()
|
||||
@@ -307,8 +360,6 @@ abstract class BaseGoogleMapFragment :
|
||||
fun switchShowLocation(@ConstantInt type: Int) {
|
||||
when (type) {
|
||||
ConstantInt.PetLocationType -> {
|
||||
//刷新下用户当前的位置
|
||||
getLastLocation()
|
||||
mPetLatLng?.let {
|
||||
mGoogleMapZoom = 17f
|
||||
refreshPetCurrentLocation(it, true)
|
||||
@@ -370,8 +421,6 @@ abstract class BaseGoogleMapFragment :
|
||||
fun setPetHeadIconUrl(petHeadUrl: String, petType: Int) {
|
||||
mPetHeadUrl = petHeadUrl
|
||||
mPetType = petType
|
||||
mPetHeadIconBitmap.safeRecycle()
|
||||
mPetHeadIconBitmap = null
|
||||
}
|
||||
|
||||
fun latLngToScreenLocation(latLng: LatLng): Point {
|
||||
@@ -946,136 +995,6 @@ abstract class BaseGoogleMapFragment :
|
||||
// LogUtil.e("点的个数:${mBlackPolyline?.points?.size},${mYellowPolyline?.points?.size}")
|
||||
// }
|
||||
|
||||
override fun onMapReady(googleMap: GoogleMap) {
|
||||
LogUtil.e("谷歌地图加载好了")
|
||||
mGoogleMap = googleMap
|
||||
|
||||
isMapLoadOk = true
|
||||
|
||||
// googleMap.uiSettings.apply {
|
||||
// //右下角工具栏不显示
|
||||
// isMapToolbarEnabled = true
|
||||
// //指南针
|
||||
// isCompassEnabled = true
|
||||
// //定位按钮
|
||||
// isMyLocationButtonEnabled = true
|
||||
// }
|
||||
|
||||
//地图样式
|
||||
setGoogleMapType()
|
||||
|
||||
googleMap.apply {
|
||||
//显示实时交通信息
|
||||
// isTrafficEnabled = true
|
||||
//检测权限,开启用户的当前位置https://developers.google.cn/maps/documentation/android-sdk/location?hl=zh-cn
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
mContext!!, Manifest.permission.ACCESS_FINE_LOCATION
|
||||
) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
|
||||
mContext!!, Manifest.permission.ACCESS_COARSE_LOCATION
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
//启用“我的位置”图层。
|
||||
isMyLocationEnabled = true
|
||||
}
|
||||
uiSettings.let {
|
||||
//禁止显示“我的位置”按钮。
|
||||
it.isMyLocationButtonEnabled = false
|
||||
//用于设置是启用还是停用倾斜手势的偏好设置。
|
||||
// https://developers.google.cn/maps/documentation/android-sdk/reference/com/google/android/libraries/maps/UiSettings?hl=zh-cn
|
||||
it.isMapToolbarEnabled = false
|
||||
it.isTiltGesturesEnabled = false
|
||||
it.isCompassEnabled = true
|
||||
}
|
||||
|
||||
onMapLoadOk(googleMap)
|
||||
}
|
||||
}
|
||||
|
||||
//*************************定位代码start****************************************
|
||||
|
||||
// The Fused Location Provider provides access to location APIs.
|
||||
private val mFusedLocationClient: FusedLocationProviderClient by lazy {
|
||||
LocationServices.getFusedLocationProviderClient(mContext!!)
|
||||
}
|
||||
private var mCancellationTokenSource: CancellationTokenSource? = null
|
||||
|
||||
|
||||
/**
|
||||
* 获取最后位置,用户当前的位置
|
||||
*/
|
||||
@SuppressLint("MissingPermission")
|
||||
fun getLastLocation() {
|
||||
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("getLastLocation:${location.latitude}, ${location.longitude}")
|
||||
} else {
|
||||
LogUtil.e("getLastLocation:exception" + taskLocation.exception)
|
||||
}
|
||||
if (null != location) {
|
||||
setUserLatLng(location)
|
||||
if (isLocationSuccessCallback) {
|
||||
setUserMarker()
|
||||
locationSuccess(location)
|
||||
}
|
||||
isLocationSuccessCallback = false
|
||||
} else requestCurrentLocation()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求用户当前的位置
|
||||
*/
|
||||
@SuppressLint("MissingPermission")
|
||||
fun requestCurrentLocation() {
|
||||
try {
|
||||
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("requestCurrentLocation $result")
|
||||
if (null != location) {
|
||||
setUserLatLng(location)
|
||||
if (isLocationSuccessCallback) locationSuccess(location)
|
||||
isLocationSuccessCallback = false
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
LogUtil.e("requestCurrentLocation异常:${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUserLatLng(location: Location) {
|
||||
location.apply {
|
||||
MMKVUtil.putDouble(MMKVKey.UserGpsLat, latitude)
|
||||
MMKVUtil.putDouble(MMKVKey.UserGpsLon, longitude)
|
||||
//单位是米/秒(m/s)
|
||||
MMKVUtil.putFloat(MMKVKey.UserGpsSpeed, speed)
|
||||
mUserLatLng = LatLng(latitude, longitude)
|
||||
}
|
||||
}
|
||||
|
||||
//*************************定位代码end****************************************
|
||||
|
||||
/**
|
||||
* 由 points 组成的区域 距离手机屏幕距离screenPaddingPx 像素单位
|
||||
@@ -1267,124 +1186,12 @@ abstract class BaseGoogleMapFragment :
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mCancellationTokenSource?.cancel()
|
||||
mGoogleMapView?.onStop()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mPetHeadIconBitmap.safeRecycle()
|
||||
mPetHeadIconBitmap = null
|
||||
mGoogleMapView?.onDestroy()
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * 两点间距离 单位米
|
||||
// */
|
||||
// private fun distanceBetween(p1: LatLng, p2: LatLng): Double {
|
||||
// val r = 6371000.0
|
||||
// val lat1 = p1.latitude * PI / 180
|
||||
// val lng1 = p1.longitude * PI / 180
|
||||
// val lat2 = p2.latitude * PI / 180
|
||||
// val lng2 = p2.longitude * PI / 180
|
||||
//
|
||||
// val dLat = lat2 - lat1
|
||||
// val dLng = lng2 - lng1
|
||||
// val a = sin(dLat / 2).pow(2) + cos(lat1) * cos(lat2) * sin(dLng / 2).pow(2)
|
||||
// val c = 2 * atan2(sqrt(a), sqrt(1 - a))
|
||||
// return r * c
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Ramer-Douglas-Peucker 轨迹抽稀平滑
|
||||
// * @param epsilon 阈值 建议0.5~2.0
|
||||
// */
|
||||
// private fun rdpSmooth(points: List<LatLng>, epsilon: Double = 1.0): List<LatLng> {
|
||||
// if (points.size < 3) return points
|
||||
// var maxDist = 0.0
|
||||
// var index = 0
|
||||
// val start = points.first()
|
||||
// val end = points.last()
|
||||
//
|
||||
// for (i in 1 until points.lastIndex) {
|
||||
// val dist = pointToLineDist(points[i], start, end)
|
||||
// if (dist > maxDist) {
|
||||
// maxDist = dist
|
||||
// index = i
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return if (maxDist > epsilon) {
|
||||
// val left = rdpSmooth(points.subList(0, index + 1), epsilon)
|
||||
// val right = rdpSmooth(points.subList(index, points.size), epsilon)
|
||||
// left.dropLast(1) + right
|
||||
// } else {
|
||||
// listOf(start, end)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 点到线段距离
|
||||
// */
|
||||
// private fun pointToLineDist(p: LatLng, a: LatLng, b: LatLng): Double {
|
||||
// val ax = a.longitude
|
||||
// val ay = a.latitude
|
||||
// val bx = b.longitude
|
||||
// val by = b.latitude
|
||||
// val px = p.longitude
|
||||
// val py = p.latitude
|
||||
//
|
||||
// val cross = (px - ax) * (bx - ax) + (py - ay) * (by - ay)
|
||||
// if (cross <= 0.0) return distanceBetween(p, a)
|
||||
//
|
||||
// val len2 = (bx - ax).pow(2) + (by - ay).pow(2)
|
||||
// if (cross >= len2) return distanceBetween(p, b)
|
||||
//
|
||||
// val t = cross / len2
|
||||
// val nearX = ax + t * (bx - ax)
|
||||
// val nearY = ay + t * (by - ay)
|
||||
// return distanceBetween(p, LatLng(nearY, nearX))
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 相邻两点插值补点,让线条更顺滑
|
||||
// * @param step 插值个数 推荐2~3
|
||||
// */
|
||||
// private fun latLngInterpolate(points: List<LatLng>, step: Int = 2): List<LatLng> {
|
||||
// if (points.size < 2) return points
|
||||
// val result = mutableListOf<LatLng>()
|
||||
// for (i in 0 until points.size - 1) {
|
||||
// val p0 = points[i]
|
||||
// val p1 = points[i + 1]
|
||||
// result.add(p0)
|
||||
// for (s in 1..step) {
|
||||
// val ratio = s.toDouble() / (step + 1)
|
||||
// val lat = p0.latitude + (p1.latitude - p0.latitude) * ratio
|
||||
// val lng = p0.longitude + (p1.longitude - p0.longitude) * ratio
|
||||
// result.add(LatLng(lat, lng))
|
||||
// }
|
||||
// }
|
||||
// result.add(points.last())
|
||||
// return result
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * GPS降噪,过滤跳点漂移
|
||||
// */
|
||||
// private fun filterNoisePoint(
|
||||
// points: List<LatLng>, minDis: Double = 5.0, maxDis: Double = 60.0
|
||||
// ): List<LatLng> {
|
||||
// if (points.isEmpty()) return emptyList()
|
||||
// val res = mutableListOf<LatLng>().apply { add(points.first()) }
|
||||
// for (i in 1 until points.size) {
|
||||
// val last = res.last()
|
||||
// val dis = distanceBetween(last, points[i])
|
||||
// if (dis in minDis..maxDis) {
|
||||
// res.add(points[i])
|
||||
// }
|
||||
// }
|
||||
// return res
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
package com.abbidot.tracker.ui.fragment.map.googlemap
|
||||
|
||||
import android.content.Context
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.abbidot.tracker.bean.WiFiZoneBean
|
||||
import com.abbidot.tracker.vm.GeoCoderViewModel
|
||||
import com.google.android.gms.maps.GoogleMap
|
||||
import com.google.android.gms.maps.model.Marker
|
||||
|
||||
/**
|
||||
*Created by .yzq on 2024/6/4/004.
|
||||
* @link
|
||||
* @description:
|
||||
*/
|
||||
class EditWiFiZoneGoogleMapFragment(
|
||||
* @description: 编辑WiFi区域地图
|
||||
* */
|
||||
class EditWiFiZoneGoogleMapFragment() : BaseGoogleMapFragment() {
|
||||
|
||||
) : BaseGoogleMapFragment() {
|
||||
|
||||
private val mGeoCoderViewModel: GeoCoderViewModel by viewModels()
|
||||
// private val mGeoCoderViewModel: GeoCoderViewModel by viewModels()
|
||||
|
||||
private lateinit var mMapLoadOk: () -> Unit
|
||||
private lateinit var mWiFiZoneBean: WiFiZoneBean
|
||||
@@ -33,34 +28,33 @@ class EditWiFiZoneGoogleMapFragment(
|
||||
|
||||
override fun onMapLoadOk(googleMap: GoogleMap) {
|
||||
|
||||
googleMap.setOnMarkerDragListener(object : GoogleMap.OnMarkerDragListener {
|
||||
override fun onMarkerDrag(marker: Marker) {
|
||||
// googleMap.setOnMarkerDragListener(object : GoogleMap.OnMarkerDragListener {
|
||||
// override fun onMarkerDrag(marker: Marker) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// override fun onMarkerDragEnd(marker: Marker) {
|
||||
// marker.position.let {
|
||||
// mGeoCoderViewModel.getLatLonAddress(it.latitude, it.longitude, false)
|
||||
// mWiFiZoneBean.latitude = it.latitude
|
||||
// mWiFiZoneBean.longitude = it.longitude
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun onMarkerDragStart(marker: Marker) {
|
||||
//
|
||||
// }
|
||||
// })
|
||||
|
||||
}
|
||||
|
||||
override fun onMarkerDragEnd(marker: Marker) {
|
||||
marker.position.let {
|
||||
mGeoCoderViewModel.getLatLonAddress(it.latitude, it.longitude, false)
|
||||
mWiFiZoneBean.latitude = it.latitude
|
||||
mWiFiZoneBean.longitude = it.longitude
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMarkerDragStart(marker: Marker) {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
getLastLocation()
|
||||
|
||||
//变量是否初始化
|
||||
if (::mMapLoadOk.isInitialized) mMapLoadOk()
|
||||
}
|
||||
|
||||
override fun liveDataObserve() {
|
||||
mGeoCoderViewModel.mLatLonAddressLiveData.observe(viewLifecycleOwner) {
|
||||
mWiFiZoneBean.address = it
|
||||
}
|
||||
}
|
||||
// override fun liveDataObserve() {
|
||||
// mGeoCoderViewModel.mLatLonAddressLiveData.observe(viewLifecycleOwner) {
|
||||
// mWiFiZoneBean.address = it
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -100,7 +100,6 @@ class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
getLastLocation()
|
||||
|
||||
//变量是否初始化
|
||||
if (::mMapLoadOk.isInitialized) mMapLoadOk()
|
||||
@@ -197,13 +196,16 @@ class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
val limitRadius = 100 / stepDistance * 50
|
||||
//限制矩形边长100m
|
||||
val limitSide = 100 / stepDistance * 100
|
||||
LogUtil.e("setScaleLimitDistance,$stepDistance,$limitRadius,$limitSide,${cameraPosition.zoom}")
|
||||
LogUtil.e("ScaleLimitDistance,$stepDistance,$limitRadius,$limitSide,${cameraPosition.zoom}")
|
||||
mFencesCircleView.mLimitRadius = limitRadius.toFloat()
|
||||
mFencesRectView.mLimitSide = limitSide.toFloat()
|
||||
mFencesPolygonView.mLimitSide = limitSide.toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回2种距离,第一个是设备使用真实距离,第二个是界面显示10的倍数距离
|
||||
*/
|
||||
private fun getLatLngAndCalDistance(): Array<String> {
|
||||
if (null == mGoogleMap) return arrayOf("0", "0")
|
||||
|
||||
@@ -227,7 +229,7 @@ class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
endLatLng.longitude
|
||||
)
|
||||
val distanceInt = distance.toInt()
|
||||
val showDistance = getShowDistance(distanceInt)
|
||||
val showDistance = Util.getShowDistance(distanceInt)
|
||||
LogUtil.e("getLatLngAndCalDistance,$distanceInt,$showDistance")
|
||||
mFencesBean.apply {
|
||||
toGpsLatLon(centreLatLng).let {
|
||||
@@ -276,9 +278,9 @@ class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
rectCLatLng.longitude
|
||||
)
|
||||
val widthDistance = rectWidthDistance.toInt()
|
||||
val showWidthDistance = getShowDistance(widthDistance)
|
||||
val showWidthDistance = Util.getShowDistance(widthDistance)
|
||||
val heightDistance = rectHeightDistance.toInt()
|
||||
val showHeightDistance = getShowDistance(heightDistance)
|
||||
val showHeightDistance = Util.getShowDistance(heightDistance)
|
||||
mFencesBean.apply {
|
||||
toGpsLatLon(centreLatLng).let {
|
||||
latitudeCenter = it.latitude
|
||||
@@ -374,16 +376,6 @@ class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取ui显示的距离,经过算法处理的
|
||||
*/
|
||||
private fun getShowDistance(distance: Int): Int {
|
||||
val singleDigit = distance % 10
|
||||
val integerDigit = distance / 10 * 10
|
||||
return if (singleDigit > 4) integerDigit + 10
|
||||
else integerDigit
|
||||
}
|
||||
|
||||
/**
|
||||
* 还原围栏
|
||||
*/
|
||||
@@ -394,14 +386,14 @@ class FencesAddEditGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
when (mFencesBean.fenceShapeType) {
|
||||
ConstantInt.CircleShapeType -> {
|
||||
restoreCircleFences()
|
||||
val showDistance = getShowDistance(radius)
|
||||
val showDistance = Util.getShowDistance(radius)
|
||||
arrayOfDistance = arrayOf("$radius", "$showDistance")
|
||||
}
|
||||
|
||||
ConstantInt.RectangleShapeType -> {
|
||||
restoreRectFences()
|
||||
val showWidthDistance = getShowDistance(longDistance)
|
||||
val showHeightDistance = getShowDistance(shortDistance)
|
||||
val showWidthDistance = Util.getShowDistance(longDistance)
|
||||
val showHeightDistance = Util.getShowDistance(shortDistance)
|
||||
arrayOfDistance = arrayOf(
|
||||
"$longDistance",
|
||||
"$shortDistance",
|
||||
|
||||
@@ -114,8 +114,6 @@ class HistoryDataGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
getLastLocation()
|
||||
|
||||
//变量是否初始化
|
||||
if (::mMapLoadOk.isInitialized) mMapLoadOk()
|
||||
}
|
||||
|
||||
@@ -181,7 +181,6 @@ class HomeMapGoogleMapFragmentV3 : BaseGoogleMapFragment() {
|
||||
return false
|
||||
}
|
||||
})
|
||||
getLastLocation()
|
||||
}
|
||||
|
||||
//变量是否初始化
|
||||
|
||||
@@ -60,12 +60,15 @@ class MarkerInfoWindowAdapter(context: Context) : GoogleMap.InfoWindowAdapter {
|
||||
LogUtil.d("$tag-----------")
|
||||
if (null == tag) return
|
||||
|
||||
if (TextUtils.isEmpty(tag.dayTime)) {
|
||||
locationUpdateTextView.visibility = View.GONE
|
||||
} else {
|
||||
locationUpdateTextView.visibility = View.VISIBLE
|
||||
locationUpdateTextView.visibility = if (TextUtils.isEmpty(tag.dayTime)) View.GONE
|
||||
else {
|
||||
locationUpdateTextView.text = tag.dayTime
|
||||
View.VISIBLE
|
||||
}
|
||||
locationTextView.visibility = if (TextUtils.isEmpty(tag.address)) View.GONE
|
||||
else {
|
||||
locationTextView.text = tag.address
|
||||
View.VISIBLE
|
||||
}
|
||||
locationTextView.text = tag.address
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ class PreviewFencesGoogleMapFragment : BaseGoogleMapFragment() {
|
||||
}
|
||||
|
||||
override fun onMapLoadOk(googleMap: GoogleMap) {
|
||||
getLastLocation()
|
||||
//变量是否初始化
|
||||
if (::mMapLoadOk.isInitialized) mMapLoadOk()
|
||||
}
|
||||
|
||||
@@ -3,8 +3,11 @@ package com.abbidot.tracker.ui.fragment.map.googlemap
|
||||
import android.content.Context
|
||||
import android.location.Location
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.bean.HistoryDataBean
|
||||
import com.abbidot.tracker.util.LonAndLatUtil
|
||||
import com.abbidot.tracker.vm.GeoCoderViewModel
|
||||
import com.google.android.gms.maps.GoogleMap
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
@@ -20,11 +23,13 @@ class WiFiZone2GoogleMapFragment : BaseGoogleMapFragment() {
|
||||
|
||||
//wifi zone当前位置信息 //保存地理信息,方便传参给其他页面
|
||||
var mDecWifiAddressData: HistoryDataBean? = null
|
||||
private var isFirstBind = false
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newInstance(context: Context) = WiFiZone2GoogleMapFragment().apply {
|
||||
fun newInstance(context: Context, firstBind: Boolean) = WiFiZone2GoogleMapFragment().apply {
|
||||
mContext = context
|
||||
isFirstBind = firstBind
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +72,6 @@ class WiFiZone2GoogleMapFragment : BaseGoogleMapFragment() {
|
||||
mMarker?.showInfoWindow()
|
||||
}
|
||||
}
|
||||
getLastLocation()
|
||||
}
|
||||
|
||||
override fun liveDataObserve() {
|
||||
@@ -106,6 +110,11 @@ class WiFiZone2GoogleMapFragment : BaseGoogleMapFragment() {
|
||||
|
||||
override fun locationSuccess(location: Location?) {
|
||||
location?.apply {
|
||||
//首次添加设备,需要判断是否超出中国边界
|
||||
if (isFirstBind) {
|
||||
val isOutOfChina = LonAndLatUtil.isLocationOutOfChina(latitude, longitude)
|
||||
MMKVUtil.putBoolean(MMKVKey.isGpsToGCJ02, !isOutOfChina)
|
||||
}
|
||||
val latLng = LatLng(latitude, longitude)
|
||||
moveCameraLocation(latLng)
|
||||
if (null == mMarker) {
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.abbidot.tracker.util
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.IBinder
|
||||
import com.abbidot.tracker.service.BaiduLocationService
|
||||
import com.easysocket.utils.LogUtil
|
||||
|
||||
/**
|
||||
* 百度定位管理器
|
||||
*/
|
||||
object BaiduLocationManager {
|
||||
|
||||
private var locationService: BaiduLocationService? = null
|
||||
private var isServiceBound = false
|
||||
|
||||
//服务连接回调
|
||||
private val serviceConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||
val binder = service as BaiduLocationService.LocalBinder
|
||||
locationService = binder.getService()
|
||||
isServiceBound = true
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(arg0: ComponentName) {
|
||||
isServiceBound = false
|
||||
locationService = null
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化:绑定服务(建议在Application或首页初始化)
|
||||
fun init(context: Context) {
|
||||
if (!isServiceBound) {
|
||||
Intent(context, BaiduLocationService::class.java).also { intent ->
|
||||
context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 启动定位(所有页面统一调用此方法)
|
||||
fun startLocation(locationPeriod: Int = 1, needStopLocation: Boolean = false) {
|
||||
locationService?.startLocation(locationPeriod, needStopLocation)
|
||||
}
|
||||
|
||||
// 停止定位
|
||||
fun stopLocation() {
|
||||
locationService?.stopLocation()
|
||||
}
|
||||
|
||||
// 释放资源(如退出应用时调用)
|
||||
fun releaseServer(context: Context) {
|
||||
try {
|
||||
if (isServiceBound) {
|
||||
LogUtil.e("onDestroy: 释放定位服务")
|
||||
context.unbindService(serviceConnection)
|
||||
isServiceBound = false
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
LogUtil.e("释放定位服务失败,releaseServer:${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.abbidot.tracker.util
|
||||
|
||||
import com.abbidot.baselibrary.constant.EventName
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.eventbus.XEventBus
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.abbidot.tracker.bean.BleReportDataBean
|
||||
import com.abbidot.tracker.bean.HistoryDataBean
|
||||
import com.abbidot.tracker.constant.ConstantInt
|
||||
@@ -86,10 +88,12 @@ class BleReportManage(
|
||||
//定位方式
|
||||
add(4)
|
||||
add(1)
|
||||
val lon = (LonAndLatUtil.currentUserGPSLon * 1000000).toLong()
|
||||
val userGpsLat = MMKVUtil.getDouble(MMKVKey.UserGpsLat)
|
||||
val userGpsLon = MMKVUtil.getDouble(MMKVKey.UserGpsLon)
|
||||
val lon = (userGpsLat * 1000000).toLong()
|
||||
val lonByteArray = SRBleCmdUtil.instance.longTo4ByteArray(lon)
|
||||
addAll(lonByteArray.toMutableList())
|
||||
val lat = (LonAndLatUtil.currentUserGPSLat * 1000000).toLong()
|
||||
val lat = (userGpsLon * 1000000).toLong()
|
||||
val latByteArray = SRBleCmdUtil.instance.longTo4ByteArray(lat)
|
||||
addAll(latByteArray.toMutableList())
|
||||
addAll(timeStampByteArray.toMutableList())
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.abbidot.tracker.util
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.IBinder
|
||||
import com.abbidot.tracker.service.GoogleLocationService
|
||||
import com.easysocket.utils.LogUtil
|
||||
|
||||
/**
|
||||
* 谷歌定位管理器
|
||||
*/
|
||||
object GoogleLocationManager {
|
||||
|
||||
private var locationService: GoogleLocationService? = null
|
||||
private var isServiceBound = false
|
||||
|
||||
//服务连接回调
|
||||
private val serviceConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||
val binder = service as GoogleLocationService.LocalBinder
|
||||
locationService = binder.getService()
|
||||
isServiceBound = true
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(arg0: ComponentName) {
|
||||
isServiceBound = false
|
||||
locationService = null
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化:绑定服务(建议在Application或首页初始化)
|
||||
fun init(context: Context) {
|
||||
if (!isServiceBound) {
|
||||
Intent(context, GoogleLocationService::class.java).also { intent ->
|
||||
context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 启动定位(所有页面统一调用此方法)
|
||||
fun startLocation() {
|
||||
locationService?.startLocation()
|
||||
}
|
||||
|
||||
// 停止定位
|
||||
fun stopLocation() {
|
||||
locationService?.stopLocation()
|
||||
}
|
||||
|
||||
// 释放资源(如退出应用时调用)
|
||||
fun releaseServer(context: Context) {
|
||||
try {
|
||||
if (isServiceBound) {
|
||||
LogUtil.e("onDestroy: 释放定位服务")
|
||||
context.unbindService(serviceConnection)
|
||||
isServiceBound = false
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
LogUtil.e("释放定位服务失败,releaseServer:${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.abbidot.tracker.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.abbidot.baselibrary.util.LogUtil;
|
||||
import com.google.android.gms.location.FusedLocationProviderClient;
|
||||
import com.google.android.gms.location.LocationCallback;
|
||||
import com.google.android.gms.location.LocationRequest;
|
||||
import com.google.android.gms.location.LocationResult;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
|
||||
/**
|
||||
* Created by .yzq on 2023/10/18/018.
|
||||
*
|
||||
* @link <a href="https://www.cnblogs.com/CharlesGrant/p/8242413.html"/>
|
||||
* @description: 谷歌定位,暂未使用
|
||||
*/
|
||||
public class GoogleLocationUtil {
|
||||
private LocationRequest mLocationRequest;
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
public GoogleLocationUtil(Context context) {
|
||||
createLocationRequest();
|
||||
|
||||
FusedLocationProviderClient fusedLocationClient =
|
||||
LocationServices.getFusedLocationProviderClient(context);
|
||||
|
||||
LogUtil.Companion.e("GoogleLocationUtil");
|
||||
|
||||
// LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
|
||||
//
|
||||
// builder.addLocationRequest(mLocationRequest);
|
||||
|
||||
fusedLocationClient.requestLocationUpdates(mLocationRequest, new LocationCallback() {
|
||||
@Override
|
||||
public void onLocationResult(@NonNull LocationResult locationResult) {
|
||||
super.onLocationResult(locationResult);
|
||||
LogUtil.Companion.e("onLocationResult" + locationResult.getLastLocation());
|
||||
}
|
||||
}, Looper.myLooper());
|
||||
|
||||
fusedLocationClient.getLastLocation().addOnSuccessListener((Activity) context, location -> {
|
||||
if (location != null) {
|
||||
// Logic to handle location object
|
||||
LogUtil.Companion.e("addOnSuccessListener" + location.getLatitude());
|
||||
} else {
|
||||
// Handle null case or Request periodic location update https://developer.android.com/training/location/receive-location-updates
|
||||
LogUtil.Companion.e("addOnSuccessListener,location == null");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void createLocationRequest() {
|
||||
mLocationRequest = LocationRequest.create();
|
||||
//更新间隔
|
||||
mLocationRequest.setInterval(2000);
|
||||
mLocationRequest.setFastestInterval(1000);
|
||||
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -232,9 +232,7 @@ object ImageUtil {
|
||||
*/
|
||||
fun getBitmapFromDrawableAndSvg(context: Context, @DrawableRes drawableId: Int): Bitmap? {
|
||||
return when (val drawable = ContextCompat.getDrawable(context, drawableId)) {
|
||||
is BitmapDrawable -> {
|
||||
drawable.bitmap
|
||||
}
|
||||
is BitmapDrawable -> drawable.bitmap
|
||||
|
||||
is VectorDrawable, is VectorDrawableCompat -> {
|
||||
val bitmap = Bitmap.createBitmap(
|
||||
|
||||
@@ -16,10 +16,6 @@ class LonAndLatUtil {
|
||||
|
||||
companion object {
|
||||
|
||||
//当前用户的GPS经纬度
|
||||
var currentUserGPSLat = 0.0
|
||||
var currentUserGPSLon = 0.0
|
||||
|
||||
private const val a = 6378245.0
|
||||
private const val ee = 0.00669342162296594323
|
||||
|
||||
|
||||
@@ -96,6 +96,16 @@ class Util {
|
||||
return Utils.formatDecimal(dis).toDouble()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取地图ui显示的距离,以10的倍数显示
|
||||
*/
|
||||
fun getShowDistance(distance: Int): Int {
|
||||
val singleDigit = distance % 10
|
||||
val integerDigit = distance / 10 * 10
|
||||
return if (singleDigit > 4) integerDigit + 10
|
||||
else integerDigit
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换英制单位
|
||||
* @param type 0=in 1=lbs 2=mph 3=ft
|
||||
|
||||
@@ -89,6 +89,8 @@ class DeviceDFUViewModel(application: Application) : AndroidViewModel(applicatio
|
||||
newVersion = true
|
||||
break
|
||||
}
|
||||
//只要有一位本地版本号大于服务版本号,就认为是新版本号,无需更新
|
||||
else if (serviceVersions[i].toInt() < localVersions[i].toInt()) break
|
||||
}
|
||||
return newVersion
|
||||
} catch (e: Exception) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.abbidot.tracker.constant.ConstantInt
|
||||
import com.abbidot.tracker.ui.fragment.map.baidumap.BaseBaiduMapFragment
|
||||
import com.abbidot.tracker.ui.fragment.map.googlemap.BaseGoogleMapFragment
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
*Created by .yzq on 2022/3/2/002.
|
||||
@@ -121,7 +122,7 @@ class FencesMapViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
if (null == fencesList) return
|
||||
if (fencesList.size == 0) return
|
||||
if (fencesList.isEmpty()) return
|
||||
|
||||
val saveFillColor = ContextCompat.getColor(context, R.color.select_color4)
|
||||
var saveStrokeColor = ContextCompat.getColor(context, R.color.select_color)
|
||||
@@ -190,10 +191,24 @@ class FencesMapViewModel : ViewModel() {
|
||||
}
|
||||
} else if (mapFragment is BaseBaiduMapFragment) {
|
||||
if (it.fenceShapeType == ConstantInt.CircleShapeType) {
|
||||
var mapRadius = it.radius
|
||||
mapFragment.mBaiduMap?.let { map ->
|
||||
val pointCentre = map.projection.toScreenLocation(
|
||||
mapFragment.getBaiduMapLatLng(
|
||||
it.latitudeCenter, it.longitudeCenter
|
||||
)
|
||||
)
|
||||
val pointLineEnd = map.projection.toScreenLocation(
|
||||
mapFragment.getBaiduMapLatLng(
|
||||
it.ancillaryLatitude, it.ancillaryLongitude
|
||||
)
|
||||
)
|
||||
mapRadius = abs(pointLineEnd.x - pointCentre.x)
|
||||
}
|
||||
mapFragment.addCircleDashedAndImageFence(
|
||||
it.latitudeCenter,
|
||||
it.longitudeCenter,
|
||||
it.radius.toDouble(),
|
||||
mapRadius.toDouble(),
|
||||
imageTypeResId,
|
||||
strokeColor,
|
||||
fillColor
|
||||
|
||||
@@ -8,7 +8,6 @@ import androidx.lifecycle.ViewModel
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
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
|
||||
@@ -99,8 +98,6 @@ class GoogleLocationViewModel : ViewModel() {
|
||||
MMKVUtil.putDouble(MMKVKey.UserGpsLon, longitude)
|
||||
//单位是米/秒(m/s)
|
||||
MMKVUtil.putFloat(MMKVKey.UserGpsSpeed, speed)
|
||||
LonAndLatUtil.currentUserGPSLat = location.latitude
|
||||
LonAndLatUtil.currentUserGPSLon = location.longitude
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
android:gravity="start"
|
||||
android:text="@string/txt_help_status_network"
|
||||
android:textSize="@dimen/textSize16"
|
||||
app:lineHeight="@dimen/textSize18" />
|
||||
app:lineHeight="@dimen/textSize22" />
|
||||
|
||||
<com.abbidot.tracker.widget.TypefaceTextView
|
||||
style="@style/my_TextView_style_v2"
|
||||
@@ -73,55 +73,7 @@
|
||||
android:gravity="start"
|
||||
android:text="@string/txt_help_status_bluetooth"
|
||||
android:textSize="@dimen/textSize16"
|
||||
app:lineHeight="@dimen/textSize18" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.abbidot.tracker.widget.TypefaceTextView
|
||||
style="@style/my_TextView_style_v2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start"
|
||||
android:text="@string/txt_help_status_wifi_zone"
|
||||
android:textSize="@dimen/textSize16"
|
||||
app:lineHeight="@dimen/textSize18" />
|
||||
|
||||
<com.abbidot.tracker.widget.TypefaceTextView
|
||||
style="@style/my_TextView_style_v2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start"
|
||||
android:text="@string/txt_help_status_battery"
|
||||
android:textSize="@dimen/textSize16"
|
||||
app:lineHeight="@dimen/textSize18" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.abbidot.tracker.widget.TypefaceTextView
|
||||
style="@style/my_TextView_style_v2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start"
|
||||
android:text="@string/txt_help_status_gps"
|
||||
android:textSize="@dimen/textSize16"
|
||||
app:lineHeight="@dimen/textSize18" />
|
||||
|
||||
<com.abbidot.tracker.widget.TypefaceTextView
|
||||
style="@style/my_TextView_style_v2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start"
|
||||
android:text="@string/txt_help_status_led"
|
||||
android:textSize="@dimen/textSize16"
|
||||
app:lineHeight="@dimen/textSize18" />
|
||||
app:lineHeight="@dimen/textSize22" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
<include
|
||||
@@ -129,7 +81,7 @@
|
||||
layout="@layout/layout_help_title1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_18" />
|
||||
android:layout_marginTop="@dimen/dp_16" />
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -43,43 +43,29 @@
|
||||
<!--http://stackoverflow.com/questions/17502824/whats-wrong-with-this-format-string-->
|
||||
|
||||
<!--简体中文-Android-->
|
||||
<!-- diff -->
|
||||
|
||||
<string name="acccount_height_how_detail">从地面测量到宠物肩胛骨的最高点</string>
|
||||
<string name="tracker_manage_set_battery">电量:%s%%</string>
|
||||
<string name="pet_managet_age">%s年</string>
|
||||
|
||||
<string name="map_current_update_time">更新时间:%s</string>
|
||||
|
||||
|
||||
<string name="select_puzzle_photos">请选择2 \~ 9张照片</string>
|
||||
|
||||
<string name="pet_manage_weight">%d磅</string>
|
||||
<string name="txt_about_version">版本%s</string>
|
||||
<string name="txt_service_contract">服务协议</string>
|
||||
<string name="txt_read_and_accept">接受隐私政策与条款。</string>
|
||||
<string name="txt_device_has_bind">该设备已被%s绑定</string>
|
||||
<string name="txt_activity_goal">运动目标</string>
|
||||
<string name="txt_end_time">结束时间</string>
|
||||
|
||||
<string name="txt_fix_goal_tip">为宠物定制每日趣味活动,专注早晚互动,兼顾其需求、物种与品种</string>
|
||||
<string name="txt_invite">+\t邀请</string>
|
||||
<string name="txt_invite_family_tip">共享的家庭成员可查看宠物位置和日期,但无法编辑</string>
|
||||
|
||||
<string name="txt_otp_verification_tips">请输入发送至 %s 的4位数验证码</string>
|
||||
<string name="txt_time_remaining">剩余时间:\t</string>
|
||||
|
||||
<string name="txt_create_account_terms1">注册即表示接受服务条款和隐私政策</string>
|
||||
<string name="txt_pair_tracker_tip">确认6字符ID与追踪器背面一致</string>
|
||||
<string name="txt_input_id_tip">在设备背面找到6位数ID</string>
|
||||
<string name="txt_add_tracker_tip">设备ID错误,请核对后重试</string>
|
||||
|
||||
<string name="txt_success_paired">配对成功</string>
|
||||
<string name="txt_expires_on">有效期至</string>
|
||||
<string name="txt_renew_year1">(续订价</string>
|
||||
<string name="txt_is_pet_home">这是您宠物的常驻地吗?</string>
|
||||
|
||||
|
||||
<string name="txt_unassign_other">解绑 %s</string>
|
||||
<string name="txt_family_delete">您确定要删除家庭成员%s</string>
|
||||
<string name="txt_ble_permissions_tip">•\t 确保活动数据同步准确的必要条件。</string>
|
||||
<string name="txt_location_permissions_tip">•\t 在地图上显示您自己的位置 \n•\t 同步活动数据所必需 \n•\t 提升追踪器精度</string>
|
||||
<string name="txt_notice_permissions_tip">•\t 允许接收通知以掌握重要信息,例如您的爱宠是否离开了安全区域,或者您是否该考虑为设备充电了。</string>
|
||||
@@ -88,10 +74,7 @@
|
||||
<string name="txt_tracker_battery_tip4">选择“宠物” > “追踪器” ,点击“GPS更新间隔” ,选择3/5/10/15分钟。</string>
|
||||
<string name="txt_tracker_battery_tip5">(更短的网络连接间隔会更快耗尽设备电量。默认情况下,网络每15分钟重新连接一次。)</string>
|
||||
<string name="txt_tracker_battery_tip6">当直播开启时,追踪器进入快速定位和联网状态,通常在15-20秒内完成。此模式耗电最快,因此最好仅在紧急情况下使用。</string>
|
||||
|
||||
<string name="txt_renewal_year1">续费:</string>
|
||||
<string name="txt_month_unit">/月 x%s</string>
|
||||
|
||||
<string name="txt_change_email_tip">将发送验证码至 %s</string>
|
||||
<string name="txt_upgrade_unlock">升级至高级版,解锁独家功能!</string>
|
||||
<string name="txt_new_firmware_version">检测到新固件版本:%s</string>
|
||||
@@ -115,67 +98,16 @@
|
||||
<string name="txt_package_permission2">1.设备1次更换\n2. 专属客户支持\n3. 年度保障服务</string>
|
||||
<string name="txt_package_permission3">1. VIP 优先支持\n2. 快速更换服务(含1次)\n3. 增强型保障\n4. 无忧宠物保护</string>
|
||||
<string name="txt_min_unit_lower">%s 分钟</string>
|
||||
|
||||
<string name="txt_duration_min_unit">%s 分钟</string>
|
||||
<string name="txt_legal_info_content">欢迎使用爱彼宠物!为了更好地保障您的权益,我们将在本《隐私政策》声明中向您说明我们如何收集、使用、处理和保障您提供给我们的信息。请仔细阅读《隐私政策》和《服务条款》。</string>
|
||||
<string name="start_txt_yes">是的</string>
|
||||
<string name="tracker_number">%d个设备</string>
|
||||
<string name="pet_number">%d只</string>
|
||||
<string name="pet_manage_height">%d 英寸</string>
|
||||
<string name="txt_permissions_fail_tips">未能获得许可</string>
|
||||
<string name="no_pet">无宠物</string>
|
||||
<string name="no_bind_pet">请先绑定宠物</string>
|
||||
<string name="txt_battery_unit">%d%%</string>
|
||||
<string name="txt_pet_birthdayDate">%d年%d月</string>
|
||||
<string name="selector_folder_video_easy_photos">全部视频</string>
|
||||
<string name="selector_action_done_easy_photos">完成(%1$d/%2$d)</string>
|
||||
<string name="selector_reach_max_hint_easy_photos">最多支持%d个图片或视频</string>
|
||||
<string name="selector_reach_max_image_hint_easy_photos">最多支持%d个图片</string>
|
||||
<string name="selector_reach_max_video_hint_easy_photos">最多支持%d个视频</string>
|
||||
<string name="selector_image_size_error_easy_photos">照片的宽度应大于%1$d,高度应大于%1$d</string>
|
||||
<string name="permissions_again_easy_photos">请允许相关权限</string>
|
||||
<string name="permissions_die_easy_photos">请允许相关权限</string>
|
||||
<string name="preview_current_number_easy_photos">%1$d/%2$d</string>
|
||||
<string name="txt_today_date">今天\t%s</string>
|
||||
<string name="video_selection_easy_photos">选择视频</string>
|
||||
<string name="txt_dollar">¥\t%.2f</string>
|
||||
<string name="txt_goal_percent">%s%%</string>
|
||||
<string name="txt_reset_password_tips">输入您档案的注册邮箱,我们将发送4位数验证码至该邮箱</string>
|
||||
<string name="txt_money_unit">$%s</string>
|
||||
<string name="txt_per_month_money">$%s/月</string>
|
||||
<string name="txt_per_year_money">$%s/年</string>
|
||||
<string name="txt_delete_pet_data">这将从您的账户中永久删除所有 %s 数据</string>
|
||||
<string name="txt_renew_year">(按每年 $%s 续订)</string>
|
||||
<string name="txt_activity_success">激活成功!</string>
|
||||
<string name="txt_start_min_live">正在启动 %s-分钟直播</string>
|
||||
<string name="txt_code_valid_min">验证码有效期为 %ss</string>
|
||||
<string name="txt_family_invitation_dec">您的朋友 %s 邀请您成为 %s 的家人。</string>
|
||||
<string name="txt_renewal_year">续费:$%s/年,于%s</string>
|
||||
<string name="txt_renewal_month">续费:$%s/月,于%s</string>
|
||||
<string name="txt_annual_care">年度保险</string>
|
||||
<string name="txt_auto_subscription_year">(此后按每年 $%s 续订)</string>
|
||||
<string name="txt_auto_subscription_month">(此后按每月 $%s 续订)</string>
|
||||
<string name="txt_fail">失败</string>
|
||||
<string name="txt_edit_pay_method">编辑付款方式</string>
|
||||
<string name="txt_no_signal_tip">无信号。请检查宠物是否在室内。</string>
|
||||
<string name="txt_credit_card_exists">卡号已存在。是否覆盖?</string>
|
||||
<string name="txt_please_enter_pws">请输入密码。</string>
|
||||
<string name="txt_please_enter_email">请输入邮箱。</string>
|
||||
<string name="txt_wifi_password_dec">当移动信号弱时,Wi-Fi可确保设备保持连接</string>
|
||||
<string name="txt_renewal_day">续费:$%s/%s天,于%s</string>
|
||||
<string name="txt_day_unit">/天 x%s</string>
|
||||
<string name="txt_location_tip">ABBIDOT应用收集位置数据,可计算当前位置与设备之间的路线和距离。</string>
|
||||
<string name="txt_auto_subscription_day">(之后按$%s每天续费)</string>
|
||||
<string name="txt_auto_subscription_days">(之后按$%s/%s天续费)</string>
|
||||
<string name="txt_auto_subscription_years">(之后按$%s/%s年续费)</string>
|
||||
<string name="txt_auto_subscription_months">(之后按$%s/%s月续费)</string>
|
||||
<string name="txt_year_care">%s 年保险</string>
|
||||
<string name="txt_expiry_time">到期时间:</string>
|
||||
<string name="txt_replacement_year">1年 1 次无理由换新</string>
|
||||
<string name="txt_bluetooth_radar">蓝牙雷达</string>
|
||||
<string name="txt_fence_saved">已保存,上线时生效。</string>
|
||||
<string name="txt_renewal_years">续订:$%s / %s 年,于 %s</string>
|
||||
<string name="txt_renewal_months">续订:$%s / %s 月,于 %s</string>
|
||||
<string name="txt_refund_expired">退款期限已过</string>
|
||||
<string name="txt_refund_policy">退款政策\n</string>
|
||||
<string name="txt_automatic_refund">自动退款(48小时内)</string>
|
||||
@@ -184,128 +116,77 @@
|
||||
<string name="txt_standard_refund_dec">在最初的48小时之后,用户可在购买后30天内申请退款。\n\t1. 所有订阅计划(3个月、1年、2年)均符合条件\n\t2. 退款申请需经过审核和批准\n\t3. 退款可能会根据使用情况和服务消耗进行部分调整\n</string>
|
||||
<string name="txt_no_refund_dec">超过30天的订阅不可退款。</string>
|
||||
<string name="txt_no_refund">30天后不退款</string>
|
||||
<string name="txt_garden">花园</string>
|
||||
<string name="txt_park">公园</string>
|
||||
<string name="txt_play">玩耍</string>
|
||||
<string name="txt_unsafe">不安全</string>
|
||||
<string name="txt_vegetable_garden">菜园</string>
|
||||
<string name="txt_water">水域</string>
|
||||
<string name="login_txt_welcome">欢迎</string>
|
||||
<string name="login_txt_email">邮箱</string>
|
||||
<string name="login_txt_phone">手机号</string>
|
||||
<string name="login_txt_password">密码</string>
|
||||
<string name="login_txt_fogot">忘记密码?</string>
|
||||
<string name="login_txt_login_wechat">微信登录</string>
|
||||
<string name="login_txt_login_code">验证码登录</string>
|
||||
|
||||
|
||||
<string name="txt_code_success">验证码已发送</string>
|
||||
<string name="login_txt_no_account">没有账号?</string>
|
||||
|
||||
<string name="login_txt_no_account_sign_up">注册</string>
|
||||
|
||||
<string name="register_txt_back_login">返回登录</string>
|
||||
|
||||
<string name="register_txt_name">昵称</string>
|
||||
|
||||
<string name="register_txt_next">下一步</string>
|
||||
<string name="register_txt_resend">重新发送</string>
|
||||
<string name="register_txt_agree">同意《服务协议》和《隐私政策》</string>
|
||||
<string name="register_txt_agree1">请阅读并同意</string>
|
||||
<string name="register_txt_agree2">和</string>
|
||||
<string name="register_txt_terms">《服务协议》</string>
|
||||
<string name="register_txt_policy">《隐私政策》</string>
|
||||
<string name="register_txt_submit">提交</string>
|
||||
|
||||
|
||||
<string name="system_txt_map">地图</string>
|
||||
<string name="system_txt_profile">我的</string>
|
||||
|
||||
|
||||
<string name="txt_feedback">反馈中心</string>
|
||||
<string name="txt_setting">设置</string>
|
||||
|
||||
<string name="txt_setting_notification">消息中心</string>
|
||||
|
||||
<string name="txt_setting_account">帐户</string>
|
||||
<string name="txt_setting_about">关于</string>
|
||||
<string name="txt_setting_clear">清除缓存</string>
|
||||
|
||||
<string name="txt_feedback_title">反馈中心</string>
|
||||
<string name="txt_feedback_type">问题类型(必填)</string>
|
||||
<string name="txt_feedback_type_app">关于APP</string>
|
||||
<string name="txt_feedback_type_tracker">关于设备</string>
|
||||
<string name="txt_feedback_type_others">其它</string>
|
||||
<string name="txt_feedback_enter">请输入您的问题或建议</string>
|
||||
<string name="txt_feedback_notype">请选择问题类型</string>
|
||||
<string name="txt_feedback_email">请留下您的邮箱,以便我们更快地帮助您</string>
|
||||
<string name="acccount_img">上传图片</string>
|
||||
<string name="acccount_name">名称</string>
|
||||
|
||||
<string name="acccount_birthday">生日</string>
|
||||
|
||||
<string name="acccount_email">邮箱</string>
|
||||
|
||||
<string name="acccount_breed">品种</string>
|
||||
<string name="acccount_weight">体重</string>
|
||||
<string name="acccount_height">肩高</string>
|
||||
<string name="acccount_height_how">如何测量身高</string>
|
||||
<string name="acccount_btn_save">保存</string>
|
||||
<string name="acccount_label">标签</string>
|
||||
|
||||
<string name="tracker_activate">激活</string>
|
||||
|
||||
<string name="tracker_activate_no">不用了,谢谢</string>
|
||||
|
||||
<string name="tracker_manage">我的设备</string>
|
||||
|
||||
<string name="tracker_manage_mine">我的设备</string>
|
||||
|
||||
<string name="tracker_manage_led">LED灯</string>
|
||||
|
||||
|
||||
<string name="tracker_manage_add_pet">新宠物</string>
|
||||
<string name="tracker_manage_set_unbind">解绑</string>
|
||||
<string name="tracker_manage_set_network">网络</string>
|
||||
<string name="tracker_manage_set_gps">GPS</string>
|
||||
|
||||
<string name="tracker_manage_set_ble_connect">蓝牙已连接</string>
|
||||
<string name="tracker_manage_set_ble_unconnect">蓝牙未连接</string>
|
||||
<string name="tracker_manage_set_led">LED灯</string>
|
||||
<string name="tracker_manage_set_led_off">关</string>
|
||||
<string name="tracker_manage_set_led_on">开</string>
|
||||
|
||||
<string name="tracker_manage_set_family">家人</string>
|
||||
|
||||
<string name="tracker_manage_set_add_family_invite">邀请</string>
|
||||
<string name="tracker_manage_set_add_family_succ">发送成功</string>
|
||||
<string name="tracker_manage_set_add_family_back">返回</string>
|
||||
<string name="tracker_manage_set_duration">追踪间隔</string>
|
||||
|
||||
<string name="tracker_manage_set_fence_name">名称</string>
|
||||
<string name="tracker_manage_set_fence_shape">形式</string>
|
||||
<string name="tracker_manage_set_fence_activate">启用围栏</string>
|
||||
|
||||
<string name="tracker_manage_set_finish">完成</string>
|
||||
|
||||
<string name="tracker_light_mode_sustained">常亮</string>
|
||||
<string name="tracker_light_mode_breathing">呼吸</string>
|
||||
|
||||
<string name="tracker_light_mode_flash">快闪</string>
|
||||
<string name="pet_manage">我的宠物</string>
|
||||
|
||||
<string name="pet_manage_gender_male">雄</string>
|
||||
<string name="pet_manage_gender_female">雌</string>
|
||||
|
||||
<string name="pet_manage_detail_edit">编辑</string>
|
||||
<string name="pet_manage_detail_title2">活动勋章</string>
|
||||
|
||||
<string name="map_live_btn_stop">停止直播</string>
|
||||
|
||||
<string name="map_navigate_select_map">选择地图</string>
|
||||
<string name="map_navigate_map_google">谷歌地图</string>
|
||||
<string name="map_navigate_map_gaode">高德地图</string>
|
||||
<string name="map_navigate_cancel">取消</string>
|
||||
<string name="txt_no_install">APP未安装,请先下载安装</string>
|
||||
<string name="data_active_time">运动时间</string>
|
||||
|
||||
|
||||
<string name="data_active_calories">卡路里</string>
|
||||
|
||||
<string name="data_active_goal_set">设置目标</string>
|
||||
<string name="data_active_btn_change">修改</string>
|
||||
<string name="data_active_btn_current">当前</string>
|
||||
@@ -315,24 +196,16 @@
|
||||
<string name="txt_not_null">请完整填写</string>
|
||||
<string name="txt_successful">成功</string>
|
||||
<string name="txt_upload_successful">上传成功</string>
|
||||
<string name="txt_add_successful">添加成功</string>
|
||||
<string name="txt_save_successful">保存成功</string>
|
||||
<string name="txt_login_successful">登录成功</string>
|
||||
<string name="txt_change_successful">修改成功</string>
|
||||
<string name="txt_tips">提示</string>
|
||||
<string name="txt_add_fences">添加围栏</string>
|
||||
<string name="no_data">无数据</string>
|
||||
<string name="txt_delete_success">成功删除</string>
|
||||
<string name="txt_delete_tips">确定要删除?</string>
|
||||
<string name="txt_unbind_tips">确定要解绑设备?</string>
|
||||
<string name="txt_unbind_success">解绑成功</string>
|
||||
<string name="txt_bind_success">绑定成功</string>
|
||||
<string name="txt_today">今天</string>
|
||||
<string name="txt_min">分钟</string>
|
||||
<string name="txt_distance_unit">英里</string>
|
||||
<string name="txt_calorie_unit">大卡</string>
|
||||
<string name="txt_persisted_unit">天</string>
|
||||
<string name="txt_device_renewal">您的设备已过期,请充值</string>
|
||||
<string name="txt_stop_live_tips">停止直播?</string>
|
||||
<string name="txt_delete">删除</string>
|
||||
<string name="txt_cancel">取消</string>
|
||||
@@ -340,110 +213,43 @@
|
||||
<string name="txt_sure">确定</string>
|
||||
<string name="txt_notifications">通知</string>
|
||||
<string name="txt_net_error">请求失败,请重试</string>
|
||||
<string name="txt_load_map">地图加载中…</string>
|
||||
<string name="hello_blank_fragment">你好,空白片段</string>
|
||||
<string name="selector_folder_all_easy_photos">全部图片</string>
|
||||
<string name="selector_folder_all_video_photo_easy_photos">图片和视频</string>
|
||||
<string name="selector_easy_photos">选择</string>
|
||||
<string name="selector_preview_easy_photos">预览</string>
|
||||
<string name="selector_single_type_hint_easy_photos">只能选择一种类型的文件</string>
|
||||
<string name="msg_no_camera_easy_photos">无法启动相机</string>
|
||||
<string name="camera_temp_file_error_easy_photos">图片错误</string>
|
||||
<string name="selector_permission_error_easy_photos">请允许相关权限</string>
|
||||
<string name="selector_image_type_error_easy_photos">不支持该图像格式</string>
|
||||
<string name="edit_easy_photos">编辑</string>
|
||||
<string name="empty_easy_photos">清除</string>
|
||||
<string name="no_photos_easy_photos">没有匹配的照片</string>
|
||||
<string name="no_videos_easy_photos">没有匹配的视频</string>
|
||||
<string name="original_easy_photos">原始</string>
|
||||
<string name="done_easy_photos">完成</string>
|
||||
<string name="cancel_easy_photos">取消</string>
|
||||
<string name="template_easy_photos">模板</string>
|
||||
<string name="text_sticker_easy_photos">文本</string>
|
||||
<string name="text_sticker_date_easy_photos">日期</string>
|
||||
<string name="text_sticker_hint_easy_photos">双击编辑</string>
|
||||
<string name="text_sticker_hint_name_easy_photos">自定义</string>
|
||||
<string name="picture_selection_easy_photos">选择照片</string>
|
||||
<string name="gif_easy_photos">GIF</string>
|
||||
<string name="txt_card_auto_sub">自动订阅:</string>
|
||||
<string name="txt_card_recharge">充值</string>
|
||||
<string name="txt_pay_order_total">总计</string>
|
||||
<string name="txt_pay_order_add_card">添加新卡</string>
|
||||
<string name="txt_pay_order_payment_title">支付详情</string>
|
||||
<string name="txt_pay_order_payment_again">重试</string>
|
||||
<string name="txt_pay_order_payment_back">返回</string>
|
||||
<string name="txt_log_out_tips">确定要退出登录吗?</string>
|
||||
<string name="txt_clear_cache_tips">确定要清除缓存?</string>
|
||||
<string name="txt_light_mode">灯光模式</string>
|
||||
<string name="txt_firmware_upgrade">固件升级</string>
|
||||
<string name="txt_feedback_success">提交成功</string>
|
||||
<string name="txt_clear_cache_success">清除成功</string>
|
||||
<string name="txt_loading">加载中...</string>
|
||||
<string name="txt_token_overdue">登录失败,请重新登录</string>
|
||||
<string name="txt_auto_recharge_title">确定要取消自动订阅?</string>
|
||||
<string name="txt_auto_recharge_content">自动订阅更方便,因为您不必担心订阅过期</string>
|
||||
<string name="txt_card_number">卡号</string>
|
||||
<string name="txt_cardholder_name">持卡人姓名</string>
|
||||
<string name="card_holder">持卡人</string>
|
||||
<string name="expiry">截止日期</string>
|
||||
<string name="txt_validity_card">MM/YY</string>
|
||||
<string name="txt_cvv_card">CVV</string>
|
||||
<string name="txt_pay_success">支付成功</string>
|
||||
<string name="txt_pay_fail">支付失败,请重试</string>
|
||||
<string name="txt_card_validity_format">失效日期</string>
|
||||
<string name="txt_card_number_format">信用卡格式无效</string>
|
||||
<string name="txt_turnoff_tips">您确定要关闭设备吗?</string>
|
||||
<string name="txt_crop">裁剪图片</string>
|
||||
<string name="txt_connecting">连接中…</string>
|
||||
<string name="txt_close_account_tips">注销账户将删除账户下所有的数据,是否继续?</string>
|
||||
<string name="txt_exit_return">再次返回退出程序</string>
|
||||
<string name="txt_user_password_error">用户名或密码错误</string>
|
||||
<string name="txt_verify_code_error">验证码错误</string>
|
||||
<string name="txt_verify_code_expire">验证码已过期</string>
|
||||
<string name="txt_register_fail">注册失败</string>
|
||||
<string name="txt_user_no_exist">用户不存在</string>
|
||||
<string name="txt_user_has_exist">用户已存在</string>
|
||||
<string name="txt_email_format_error">邮箱格式不对</string>
|
||||
<string name="txt_disconnect_tips">是否断开连接设备?</string>
|
||||
<string name="txt_connect_success">连接成功</string>
|
||||
<string name="txt_connect_fail">连接失败</string>
|
||||
<string name="txt_register_phone">请输入手机号</string>
|
||||
<string name="txt_find_password">找回密码</string>
|
||||
<string name="txt_about_app_name">爱彼宠物</string>
|
||||
<string name="txt_privacy_policy">隐私政策</string>
|
||||
<string name="txt_website">官网</string>
|
||||
<string name="txt_change_pwd">修改密码</string>
|
||||
<string name="txt_cancel_pay">取消支付</string>
|
||||
<string name="txt_ble_enable">请打开手机蓝牙</string>
|
||||
<string name="txt_no_share_myself">不能分享给自己</string>
|
||||
<string name="txt_device_has_bound">当前用户已经绑定该设备</string>
|
||||
<string name="txt_first_name">姓</string>
|
||||
<string name="txt_last_name">名</string>
|
||||
<string name="txt_online">在线</string>
|
||||
<string name="txt_offline">离线</string>
|
||||
<string name="txt_legal_info_title">法律信息</string>
|
||||
<string name="txt_accept">我接受</string>
|
||||
<string name="txt_deny">拒绝</string>
|
||||
<string name="txt_no_down_url">没有下载地址</string>
|
||||
<string name="txt_please_wait">请稍等…</string>
|
||||
<string name="txt_release_notes">版本说明</string>
|
||||
<string name="txt_firmware_name">固件名称</string>
|
||||
<string name="txt_firmware_version">固件版本</string>
|
||||
<string name="txt_firmware_size">固件大小</string>
|
||||
<string name="txt_upgrade">升级</string>
|
||||
<string name="txt_upgrade_success">升级成功</string>
|
||||
<string name="txt_upgrade_fail">升级失败</string>
|
||||
<string name="txt_down_firmware">下载固件</string>
|
||||
<string name="txt_dfu_model">进入DFU模式</string>
|
||||
<string name="txt_search_dfu">搜索DUF设备</string>
|
||||
<string name="txt_no_dfu">设备不存在</string>
|
||||
<string name="txt_connect_device">连接设备</string>
|
||||
<string name="txt_reconnect_device">重连设备</string>
|
||||
<string name="txt_unconnect">设备已断开</string>
|
||||
<string name="txt_unconnect_no">断开连接</string>
|
||||
<string name="txt_upgrading">升级中</string>
|
||||
<string name="txt_upgrade_start">准备升级</string>
|
||||
<string name="txt_device_connect_success">设备连接成功</string>
|
||||
<string name="txt_latest_version">已是最新版本</string>
|
||||
<string name="txt_activity">运动</string>
|
||||
<string name="txt_route">历史</string>
|
||||
@@ -460,7 +266,6 @@
|
||||
<string name="txt_low_zone">WiFi区域</string>
|
||||
<string name="txt_connected">已连接</string>
|
||||
<string name="txt_weak_signal">信号弱</string>
|
||||
<string name="txt_battery">电量</string>
|
||||
<string name="txt_bluetooth">蓝牙</string>
|
||||
<string name="txt_light">指示灯</string>
|
||||
<string name="txt_track_and_points">检查轨迹和地点</string>
|
||||
@@ -489,18 +294,6 @@
|
||||
<string name="txt_october">十月</string>
|
||||
<string name="txt_november">十一月</string>
|
||||
<string name="txt_december">十二月</string>
|
||||
<string name="txt_january_abbr">1月</string>
|
||||
<string name="txt_february_abbr">2月</string>
|
||||
<string name="txt_march_abbr">3月</string>
|
||||
<string name="txt_april_abbr">4月</string>
|
||||
<string name="txt_may_abbr">5月</string>
|
||||
<string name="txt_june_abbr">6月</string>
|
||||
<string name="txt_july_abbr">7月</string>
|
||||
<string name="txt_august_abbr">8月</string>
|
||||
<string name="txt_september_abbr">9月</string>
|
||||
<string name="txt_october_abbr">10月</string>
|
||||
<string name="txt_november_abbr">11月</string>
|
||||
<string name="txt_december_abbr">12月</string>
|
||||
<string name="txt_find_device_tips">声音传播速度加快时,距离更近。</string>
|
||||
<string name="txt_stop_radar">停止雷达</string>
|
||||
<string name="txt_edit_power_zone">编辑WiFi区域</string>
|
||||
@@ -516,12 +309,9 @@
|
||||
<string name="txt_add_no_go_zone">添加禁止区域</string>
|
||||
<string name="txt_edit_no_go_zone">编辑禁止区域</string>
|
||||
<string name="txt_data_board">数据面板</string>
|
||||
<string name="txt_minimum">最小值</string>
|
||||
<string name="txt_recommenced">推荐值</string>
|
||||
<string name="txt_hr">小时</string>
|
||||
<string name="txt_fix_daily_goal">设置每日目标</string>
|
||||
<string name="txt_awesome_ready_begin">太棒了!开始吧!</string>
|
||||
<string name="txt_total_activity_distance">活动总距离</string>
|
||||
<string name="txt_km_small">公里</string>
|
||||
<string name="txt_avg_activity_time">日均活动时长</string>
|
||||
<string name="txt_avg_calories">平均卡路里</string>
|
||||
@@ -549,7 +339,6 @@
|
||||
<string name="txt_minimum_characters">至少6个字符</string>
|
||||
<string name="txt_country">国家/地区</string>
|
||||
<string name="txt_email_address">电子邮箱</string>
|
||||
<string name="txt_welcome_back">欢迎回来</string>
|
||||
<string name="txt_continue">继续</string>
|
||||
<string name="txt_otp_verification">验证码</string>
|
||||
<string name="txt_sec">秒</string>
|
||||
@@ -586,15 +375,15 @@
|
||||
<string name="txt_monthly_subscription">月付</string>
|
||||
<string name="txt_per_month">/月</string>
|
||||
<string name="txt_per_year">/年</string>
|
||||
<string name="txt_popular">热门</string>
|
||||
<string name="txt_popular">超值</string>
|
||||
<string name="txt_confirm_plan">确认您的套餐</string>
|
||||
<string name="txt_device_number">设备编号</string>
|
||||
<string name="txt_terms_conditions_v2">条款与条件</string>
|
||||
<string name="txt_summary">摘要</string>
|
||||
<string name="txt_sales_tax">税费</string>
|
||||
<string name="txt_payment_method">支付方式</string>
|
||||
<string name="txt_my_card">我的卡片</string>
|
||||
<string name="txt_no_card">未找到卡片</string>
|
||||
<string name="txt_choose_card">选择卡片</string>
|
||||
<string name="txt_no_card">没有支付信息</string>
|
||||
<string name="txt_add_card">添加新卡片</string>
|
||||
<string name="txt_primary">主要支付方式</string>
|
||||
<string name="txt_make_payment">立即支付</string>
|
||||
@@ -602,18 +391,14 @@
|
||||
<string name="txt_add_payment">添加支付方式</string>
|
||||
<string name="txt_save_card">保存新卡片</string>
|
||||
<string name="txt_payment_success">支付成功</string>
|
||||
<string name="txt_mm_dd">月/年 (MM/YY)</string>
|
||||
<string name="txt_cvc">安全码 (CVC)</string>
|
||||
<string name="txt_accepted_cards">接受的支付卡</string>
|
||||
<string name="txt_set_primary_card">设为主要卡片</string>
|
||||
<string name="txt_name_card">持卡人姓名</string>
|
||||
<string name="txt_permissions">权限</string>
|
||||
<string name="txt_skip">跳过</string>
|
||||
<string name="txt_enable">启用</string>
|
||||
<string name="txt_grant_permissions">授予权限以提升体验。</string>
|
||||
<string name="txt_tracker_id">设备ID</string>
|
||||
<string name="txt_plan">套餐:</string>
|
||||
|
||||
<string name="txt_renews_on">续订日期:</string>
|
||||
<string name="txt_power_saving_zone_tip">添加常驻地可提升电池续航并提供额外安全保障</string>
|
||||
<string name="txt_power_saving_zone">建立WiFi区域</string>
|
||||
@@ -629,7 +414,6 @@
|
||||
<string name="txt_about_power_saving_zone">关于WiFi区域</string>
|
||||
<string name="txt_office_tip">在您宠物常驻地(如家中)选择一个网络。一旦进入覆盖范围,您的设备将识别此网络为WiFi区域。</string>
|
||||
<string name="txt_office">办公室</string>
|
||||
<string name="txt_save_power_tip">只要设备检测到您的爱宠处于WiFi区域内,就会关闭实时追踪以延长电池续航。</string>
|
||||
<string name="txt_save_power">省电模式</string>
|
||||
<string name="txt_tracking_pet_tip">在蓝牙范围内?可使用雷达精确定位附近y设备。实时追踪也将可用,但使用它会结束省电模式。</string>
|
||||
<string name="txt_tracking_pet">正在追踪您的宠物</string>
|
||||
@@ -654,30 +438,22 @@
|
||||
<string name="txt_to_abbidot">发送至ABBIDOT</string>
|
||||
<string name="txt_password_no_same">输入的密码不一致!</string>
|
||||
<string name="txt_no_member_yet">尚无成员</string>
|
||||
<string name="txt_invite_new">+邀请</string>
|
||||
<string name="txt_invite_members">邀请成员</string>
|
||||
|
||||
|
||||
<string name="txt_home">家</string>
|
||||
<string name="txt_live_duration">直播时长</string>
|
||||
<string name="txt_about_live_duration">关于直播时长</string>
|
||||
<string name="txt_keep_short_dec">直播模式可帮助寻找宠物,每2~3秒更新一次位置,但会消耗更多电量。默认追踪仍会提供常规更新。</string>
|
||||
<string name="txt_stop_live_dec">直播将在设定的时长结束时停止,但您也可以提前停止以节省电量。</string>
|
||||
<string name="txt_keep_it_short">请尽量缩短时长</string>
|
||||
<string name="txt_bluetooth_enabled">蓝牙</string>
|
||||
<string name="txt_location_enabled">GPS 位置</string>
|
||||
<string name="txt_receive_notice">接收通知</string>
|
||||
<string name="txt_turn_on_upper">开启</string>
|
||||
<string name="txt_activated_tips">设备未激活。请订阅后激活。</string>
|
||||
<string name="txt_search_device">正在搜索…</string>
|
||||
<string name="txt_no_search_device">请保持设备开机并靠近扫描。</string>
|
||||
<string name="txt_outside">区域外</string>
|
||||
<string name="txt_inside">区域内</string>
|
||||
<string name="txt_7days_avg">7日均值</string>
|
||||
<string name="txt_created_many_fences">创建的围栏太多了</string>
|
||||
<string name="txt_live_ended">直播已结束。直播时长可通过“直播时长”设置。</string>
|
||||
<string name="txt_weak_gps_signal">GPS信号弱</string>
|
||||
<string name="map_current_no_signal">无网络信号</string>
|
||||
<string name="txt_tracker_power_off">设备已关机</string>
|
||||
<string name="txt_starting_live">正在启动直播…</string>
|
||||
<string name="txt_con_network">正在连接网络</string>
|
||||
@@ -690,14 +466,11 @@
|
||||
<string name="txt_about_live_tip">直播将在一小时后停止,但您也可以提前停止以节省电量。</string>
|
||||
<string name="txt_resting">休息中</string>
|
||||
<string name="txt_resting_time">休息时长</string>
|
||||
<string name="txt_resting_time_uppercase">休息时间</string>
|
||||
<string name="txt_no_signal">无信号</string>
|
||||
<string name="txt_wifi">WiFi</string>
|
||||
<string name="txt_set_measurement_units">选择计量单位</string>
|
||||
<string name="txt_metric">公制 (厘米, 千克) </string>
|
||||
<string name="txt_metric">公制 (厘米, 千克)</string>
|
||||
<string name="txt_imperial">英制 (英寸, 磅)</string>
|
||||
<string name="txt_km_h">公里/小时 (km/h)</string>
|
||||
<string name="txt_mph">英里/小时 (mph)</string>
|
||||
<string name="txt_m">米 (m)</string>
|
||||
<string name="txt_ft">英尺 (ft)</string>
|
||||
<string name="txt_fences_alerts">围栏告警</string>
|
||||
@@ -715,7 +488,7 @@
|
||||
<string name="txt_yesterday">昨天</string>
|
||||
<string name="txt_power_on_off">开机/关机</string>
|
||||
<string name="txt_power_on_off_tip">充电后拔掉电源即可开机。 \n绿灯闪烁 = 已开机。</string>
|
||||
<string name="txt_active_tracker_tip">选择一个订阅 \n点击以激活追踪器 \n启用GPS和蜂窝网络追踪。</string>
|
||||
<string name="txt_active_tracker_tip">1. 选择一个订阅.\n2. 点击以激活追踪器 \n3. 启用GPS和蜂窝网络追踪。</string>
|
||||
<string name="txt_active_tracker">激活追踪器</string>
|
||||
<string name="txt_check_tracker_status_tip">(GPS和移动网络状态可能因环境而异。在给宠物佩戴前,请检查您周围的不同位置以评估GPS和网络状态。)</string>
|
||||
<string name="txt_check_tracker_status">检查设备状态</string>
|
||||
@@ -723,7 +496,6 @@
|
||||
<string name="txt_tracker_battery_tip2">将设备连接到家庭WiFi(无需密码)。在WiFi区域内,GPS将停止工作。每10-60分钟连接一次网络,功耗极低。</string>
|
||||
<string name="txt_tracker_battery_tip3">当您的追踪器在WiFi区域外时,它会激活GPS并每3/5/10/15分钟连接一次网络。</string>
|
||||
<string name="txt_tracker_battery_life">设备电池续航</string>
|
||||
<string name="txt_create_fence_tip1">前往“宠物” > “我的宠物围栏” > “管理” > “+ 新增”</string>
|
||||
<string name="txt_create_fence_tip2">定义边界:在地图上选择一个位置,调整围栏的半径或形状。</string>
|
||||
<string name="txt_create_fence_tip3">当宠物进入或离开区域时发出警报。</string>
|
||||
<string name="txt_create_pet_fence">创建宠物围栏</string>
|
||||
@@ -780,14 +552,11 @@
|
||||
<string name="txt_how_to_get">如何获取?</string>
|
||||
<string name="txt_family_invitation">邀请家人</string>
|
||||
<string name="txt_active_time1">活跃时长:</string>
|
||||
|
||||
|
||||
<string name="txt_expires_on1">有效期至:</string>
|
||||
<string name="txt_expires_on2">过期于:</string>
|
||||
<string name="txt_years">年</string>
|
||||
<string name="txt_mouths">月</string>
|
||||
|
||||
|
||||
<string name="txt_days">天</string>
|
||||
<string name="txt_subscription_history">订阅订单</string>
|
||||
<string name="txt_order_id">订单号:</string>
|
||||
<string name="txt_request_refund_dec">请输入您的退款原因</string>
|
||||
@@ -796,8 +565,9 @@
|
||||
<string name="txt_waiting">等待处理</string>
|
||||
<string name="txt_refunding">退款中</string>
|
||||
<string name="txt_refunded">已退款</string>
|
||||
|
||||
|
||||
<string name="txt_renewal_year2">/年,于</string>
|
||||
<string name="txt_renewal_month2">/月,于</string>
|
||||
<string name="txt_replace_guarantee">换新保障</string>
|
||||
<string name="txt_annual_care_text">年度护理</string>
|
||||
<string name="txt_annual_care_text1">年度护理:</string>
|
||||
<string name="txt_led_light_set">LED灯设置</string>
|
||||
@@ -846,31 +616,20 @@
|
||||
<string name="txt_account_exists_log_in">账户已存在。立即登录?</string>
|
||||
<string name="txt_time_out_of_range">所选日期超出范围</string>
|
||||
<string name="txt_power_on_off_install_tip">摇一摇开机 \n绿灯闪烁表示已开机。</string>
|
||||
<string name="txt_check_tracker_status_top_tip">前往“宠物 > 追踪器” \n检查:网络、GPS、电池、WiFi、区域、蓝牙、LED。 \nGPS和蜂窝网络信号可能因位置而异。使用前请在不同位置进行测试。</string>
|
||||
<string name="txt_check_tracker_status_top_tip">GPS 和蜂窝网络信号可能因位置而异。\n使用前,请在不同位置进行测试。</string>
|
||||
<string name="txt_on_charging">设备充电中</string>
|
||||
<string name="txt_active_subscribed">已订阅</string>
|
||||
<string name="map_baidu_map">百度地图</string>
|
||||
<string name="txt_send">发送</string>
|
||||
<string name="txt_turn_on_power">首次开机请连接电源线。之后可通过摇动开机。</string>
|
||||
<string name="txt_1_year_subscription">1年订阅</string>
|
||||
<string name="txt_2_year_subscription">2年订阅</string>
|
||||
<string name="txt_3_year_subscription">3年订阅</string>
|
||||
<string name="txt_as_low_as">低至</string>
|
||||
<string name="txt_payment_manager">支付管理</string>
|
||||
<string name="txt_billed_annually">按年计费</string>
|
||||
<string name="txt_basic_plan">基础计划</string>
|
||||
<string name="txt_premium_plan">高级计划</string>
|
||||
<string name="txt_real_time_tracking">实时追踪</string>
|
||||
<string name="txt_activity_logs">活动/休息</string>
|
||||
<string name="txt_notifications_emergencies">告警日志</string>
|
||||
<string name="txt_customized_led">自定义LED灯</string>
|
||||
<string name="txt_geofencing">电子围栏</string>
|
||||
<string name="txt_route_records">路线历史记录</string>
|
||||
<string name="txt_family_sharing">家庭成员共享</string>
|
||||
<string name="txt_customer_support">30天退款保证</string>
|
||||
<string name="txt_show_crash">程序出现异常,即将退出</string>
|
||||
<string name="txt_activate_subscribe">激活订阅</string>
|
||||
<string name="txt_powered_off">已关机</string>
|
||||
<string name="txt_charging">充电中</string>
|
||||
<string name="txt_total_time">总时间</string>
|
||||
<string name="txt_live_works_cellular">直播仅限移动网络</string>
|
||||
@@ -886,8 +645,6 @@
|
||||
<string name="txt_tone">提示音</string>
|
||||
<string name="txt_locate_works">定位仅适用于移动网络</string>
|
||||
<string name="txt_pet_close">宠物在附近,请尝试雷达</string>
|
||||
<string name="txt_load_more_pull_text">下拉加载更多</string>
|
||||
<string name="txt_load_more_release_text">释放加载</string>
|
||||
<string name="txt_fully_charged">已充满电</string>
|
||||
<string name="txt_time_line">时间线</string>
|
||||
<string name="txt_phone_close_device">保持手机靠近设备</string>
|
||||
@@ -896,26 +653,292 @@
|
||||
<string name="txt_first_use">首次使用</string>
|
||||
<string name="txt_daily_use">日常使用</string>
|
||||
<string name="txt_sleep_mode">休眠模式</string>
|
||||
<string name="txt_sleep_mode_help">15分钟无移动 → 进入休眠模式。 \n移动时自动唤醒。 \n电量每24小时更新一次</string>
|
||||
<string name="txt_sleep_mode_help">1. 15分钟无移动 → 进入休眠模式; \n2. 移动时自动唤醒; \n3. 电量每24小时更新一次。</string>
|
||||
<string name="txt_wifi_zone_home">WiFi区域(家)</string>
|
||||
<string name="txt_wifi_zone_home_help">连接家庭WiFi \n GPS关闭 → 节省电池。\n约每60分钟更新一次</string>
|
||||
<string name="txt_gps_update_help">宠物 > 追踪器 > GPS更新 \n选择3–15分钟。 \n间隔越短,耗电越高。 \n默认:5分钟</string>
|
||||
<string name="txt_wifi_zone_home_help">1. 连接家庭WiFi; \n2. GPS关闭 → 节省电池;\n3. 约每60分钟更新一次。</string>
|
||||
<string name="txt_gps_update_help">1. 选择 3–15 分钟。\n\n2. 间隔越短,耗电越高。\n\n3. 默认:5 分钟。</string>
|
||||
<string name="txt_set_fence_type">设置围栏类型</string>
|
||||
<string name="txt_fence_type_help">安全区域 或 禁止区</string>
|
||||
<string name="txt_set_boundary">设置边界</string>
|
||||
<string name="txt_enable_set_notify">在“账户 > 设置 > 通知”中启用提醒</string>
|
||||
<string name="txt_edit_delete_fence">在“管理”中编辑或删除围栏</string>
|
||||
<string name="txt_total">总计</string>
|
||||
<string name="txt_init_device">正在初始化设备</string>
|
||||
<string name="txt_add_wifi_tips">添加wifi区域可延长使用时长</string>
|
||||
<string name="txt_add">去添加</string>
|
||||
<string name="txt_already_min_size">已是最小尺寸</string>
|
||||
<string name="txt_3_months_subscription">3个月灵活套餐</string>
|
||||
<string name="txt_1_year_subscription">1年Plus套餐</string>
|
||||
<string name="txt_2_years_subscription">2年Protection+套餐</string>
|
||||
<string name="txt_billed_quarterly">按季度计费</string>
|
||||
<string name="txt_billed_annually">按年计费</string>
|
||||
<string name="txt_billed_every_2_years">每两年计费</string>
|
||||
<string name="txt_login_with">使用以下方式登录</string>
|
||||
<string name="txt_my_card">我的卡片</string>
|
||||
<string name="txt_edit_my_card">编辑支付信息</string>
|
||||
<string name="txt_phone_has_bound">该手机号码已被绑定</string>
|
||||
<string name="txt_go_to">前往</string>
|
||||
<string name="txt_pet_tracker">宠物 > 定位器</string>
|
||||
<string name="txt_pet_tracker_gps">宠物 > 定位器 > GPS 更新</string>
|
||||
<string name="txt_pet_fence_add">宠物 > 我的宠物围栏 > 管理 > + 新增</string>
|
||||
<string name="txt_check">检查:</string>
|
||||
<string name="txt_help_status_network">· 网络\n· WiFi Zone\n· GPS</string>
|
||||
<string name="txt_help_status_bluetooth">· 蓝牙\n· 电量\n· LED</string>
|
||||
<string name="register_txt_policy">《隐私政策》</string>
|
||||
<string name="txt_expires_on">过期于</string>
|
||||
<string name="map_navigate_map_google">谷歌地图</string>
|
||||
<string name="txt_upgrade_success">升级成功</string>
|
||||
<string name="txt_upgrade_fail">升级失败</string>
|
||||
<string name="txt_please_enter_email">请输入邮箱。</string>
|
||||
<string name="tracker_enter_id">输入设备ID</string>
|
||||
<string name="txt_no_signal_tip">无信号。请检查宠物是否在室内。</string>
|
||||
<string name="txt_recommenced">推荐值</string>
|
||||
<string name="txt_expiry_time">到期时间:</string>
|
||||
<string name="txt_activity_logs">活动/休息</string>
|
||||
<string name="txt_real_time_tracking">实时追踪</string>
|
||||
<string name="register_txt_noreceive">还没有收到验证码?</string>
|
||||
<string name="pet_managet_age_1">%d年</string>
|
||||
<string name="pet_manage_detail_earned">%d/100 已获得</string>
|
||||
<string name="map_current_update_time">更新时间:%s</string>
|
||||
<string name="txt_show_track_point">显示轨迹/点</string>
|
||||
<string name="txt_share_pet_tips">确定要分享\'%s\'的宠物数据</string>
|
||||
<string name="select_puzzle_photos">请选择2 \~ 9张照片</string>
|
||||
<string name="txt_pay_amount_detail1">此后以%.2f/年续订,可随时取消</string>
|
||||
<string name="txt_pay_order_off">已优惠%d</string>
|
||||
<string name="txt_pay_order_detail_sub_on">订阅计划有效期至%s</string>
|
||||
<string name="txt_pay_order_detail_sub_off">自动续订已关闭,订阅计划将在%s之后不可用</string>
|
||||
<string name="txt_confirm_save_card">保存并确认</string>
|
||||
<string name="txt_perMonth">$%s/月</string>
|
||||
<string name="txt_congratulations_tip">宠物信息设置成功,获得安全徽章!</string>
|
||||
<string name="txt_add_tracker_tip2">设备已被绑定,请核对后重试</string>
|
||||
<string name="txt_ft_unit">%s英尺 (ft)</string>
|
||||
<string name="txt_mph_unit">%s英里/小时 (mph)</string>
|
||||
<string name="txt_family_delete">您确定要删除家庭成员%s</string>
|
||||
<string name="txt_create_fence_tip4">开启通知:前往“账户” > \"设置\"。点击\"通知\"并开启。</string>
|
||||
<string name="txt_month_unit">/月 x%s</string>
|
||||
<string name="txt_year_unit">/%s 年</string>
|
||||
<string name="txt_card_list_end">截止至%s</string>
|
||||
<string name="txt_legal_info_content">欢迎使用爱彼宠物!为了更好地保障您的权益,我们将在本《隐私政策》声明中向您说明我们如何收集、使用、处理和保障您提供给我们的信息。请仔细阅读《隐私政策》和《服务条款》。</string>
|
||||
<string name="login_txt_phone">手机号</string>
|
||||
<string name="login_txt_login_wechat">微信登录</string>
|
||||
<string name="login_txt_login_code">验证码登录</string>
|
||||
<string name="login_txt_login_apple">Apple登录</string>
|
||||
<string name="login_txt_login_account">账号登录</string>
|
||||
<string name="txt_set_new_password">设置新密码</string>
|
||||
<string name="txt_code_success">验证码已发送</string>
|
||||
<string name="login_txt_login_password">密码登录</string>
|
||||
<string name="register_txt_hey">嗨,</string>
|
||||
<string name="register_txt_set_password">设置密码</string>
|
||||
<string name="register_txt_get_code">获取</string>
|
||||
<string name="register_txt_sented_code">我们已将验证码发送到您的电子邮件</string>
|
||||
<string name="register_txt_verification">验证码</string>
|
||||
<string name="register_txt_agree1">请阅读并同意</string>
|
||||
<string name="register_txt_agree2">和</string>
|
||||
<string name="register_txt_terms">《服务协议》</string>
|
||||
<string name="register_txt_bind_phone">绑定</string>
|
||||
<string name="login_txt_login_finish">完成</string>
|
||||
<string name="system_txt_data">数据</string>
|
||||
<string name="txt_my_orders">我的订单</string>
|
||||
<string name="txt_help_center">帮助中心</string>
|
||||
<string name="txt_feedback">反馈中心</string>
|
||||
<string name="txt_setting_title">设置</string>
|
||||
<string name="txt_setting_language">语言</string>
|
||||
<string name="txt_setting_logout">退出登录</string>
|
||||
<string name="txt_feedback_notype">请选择问题类型</string>
|
||||
<string name="acccount_gender">性别</string>
|
||||
<string name="acccount_location">地点</string>
|
||||
<string name="acccount_phone">手机</string>
|
||||
<string name="acccount_breed">品种</string>
|
||||
<string name="tracker_activate_cancel">激活并继续</string>
|
||||
<string name="tracker_activate_yes">激活</string>
|
||||
<string name="tracker_manage_title">设备</string>
|
||||
<string name="tracker_manage_mine">我的设备</string>
|
||||
<string name="tracker_manage_authorized">被授权的</string>
|
||||
<string name="tracker_manage_fence">围栏</string>
|
||||
<string name="tracker_manage_set">设置</string>
|
||||
<string name="tracker_manage_set_card_day">天</string>
|
||||
<string name="tracker_manage_set_led">LED灯</string>
|
||||
<string name="tracker_manage_set_Fence">围栏</string>
|
||||
<string name="tracker_manage_set_family">家人</string>
|
||||
<string name="tracker_manage_set_add_family">添加家人</string>
|
||||
<string name="tracker_manage_set_add_family_detail">邀请您的家人分享宠物的位置或活动。 家庭成员不能创建围栏或修改设置。</string>
|
||||
<string name="tracker_manage_set_add_family_back">返回</string>
|
||||
<string name="tracker_manage_set_power">关机</string>
|
||||
<string name="pet_manage_detail_title2">活动勋章</string>
|
||||
<string name="map_navigate_select_map">选择地图</string>
|
||||
<string name="map_navigate_map_gaode">高德地图</string>
|
||||
<string name="txt_no_install">APP未安装,请先下载安装</string>
|
||||
<string name="txt_add_successful">添加成功</string>
|
||||
<string name="txt_delete_success">成功删除</string>
|
||||
<string name="txt_unbind_tips">确定要解绑设备?</string>
|
||||
<string name="txt_unbind_success">解绑成功</string>
|
||||
<string name="txt_bind_success">绑定成功</string>
|
||||
<string name="txt_distance_unit">英里</string>
|
||||
<string name="txt_calorie_unit">大卡</string>
|
||||
<string name="txt_device_renewal">您的设备已过期,请充值</string>
|
||||
<string name="txt_load_map">地图加载中…</string>
|
||||
<string name="hello_blank_fragment">你好,空白片段</string>
|
||||
<string name="selector_folder_all_video_photo_easy_photos">图片和视频</string>
|
||||
<string name="selector_easy_photos">选择</string>
|
||||
<string name="selector_preview_easy_photos">预览</string>
|
||||
<string name="selector_single_type_hint_easy_photos">只能选择一种类型的文件</string>
|
||||
<string name="msg_no_camera_easy_photos">无法启动相机</string>
|
||||
<string name="camera_temp_file_error_easy_photos">图片错误</string>
|
||||
<string name="selector_image_type_error_easy_photos">不支持该图像格式</string>
|
||||
<string name="empty_easy_photos">清除</string>
|
||||
<string name="no_photos_easy_photos">没有匹配的照片</string>
|
||||
<string name="no_videos_easy_photos">没有匹配的视频</string>
|
||||
<string name="original_easy_photos">原始</string>
|
||||
<string name="done_easy_photos">完成</string>
|
||||
<string name="cancel_easy_photos">取消</string>
|
||||
<string name="template_easy_photos">模板</string>
|
||||
<string name="text_sticker_easy_photos">文本</string>
|
||||
<string name="text_sticker_date_easy_photos">日期</string>
|
||||
<string name="text_sticker_hint_easy_photos">双击编辑</string>
|
||||
<string name="text_sticker_hint_name_easy_photos">自定义</string>
|
||||
<string name="picture_selection_easy_photos">选择照片</string>
|
||||
<string name="gif_easy_photos">GIF</string>
|
||||
<string name="txt_pay_order_add_card">添加新卡</string>
|
||||
<string name="txt_pay_order_payment_title">支付详情</string>
|
||||
<string name="txt_pay_order_detail_plan">订阅计划:</string>
|
||||
<string name="txt_firmware_upgrade">固件升级</string>
|
||||
<string name="txt_feedback_success">提交成功</string>
|
||||
<string name="txt_clear_cache_success">清除成功</string>
|
||||
<string name="txt_token_overdue">登录失败,请重新登录</string>
|
||||
<string name="txt_cardholder_name">持卡人姓名</string>
|
||||
<string name="card_holder">持卡人</string>
|
||||
<string name="expiry">截止日期</string>
|
||||
<string name="txt_card_validity_format">失效日期</string>
|
||||
<string name="txt_card_number_format">信用卡格式无效</string>
|
||||
<string name="txt_turnoff_tips">您确定要关闭设备吗?</string>
|
||||
<string name="txt_crop">裁剪图片</string>
|
||||
<string name="txt_exit_return">再次返回退出程序</string>
|
||||
<string name="txt_register_fail">注册失败</string>
|
||||
<string name="txt_email_format_error">邮箱格式不对</string>
|
||||
<string name="txt_disconnect_tips">是否断开连接设备?</string>
|
||||
<string name="txt_connect_success">连接成功</string>
|
||||
<string name="txt_connect_fail">连接失败</string>
|
||||
<string name="txt_register_phone">请输入手机号</string>
|
||||
<string name="txt_about_app_name">爱彼宠物</string>
|
||||
<string name="txt_change_pwd">修改密码</string>
|
||||
<string name="txt_cancel_pay">取消支付</string>
|
||||
<string name="txt_device_has_bound">当前用户已经绑定该设备</string>
|
||||
<string name="txt_first_name">姓</string>
|
||||
<string name="txt_last_name">名</string>
|
||||
<string name="txt_legal_info_title">法律信息</string>
|
||||
<string name="txt_accept">我接受</string>
|
||||
<string name="txt_deny">拒绝</string>
|
||||
<string name="txt_no_down_url">没有下载地址</string>
|
||||
<string name="txt_please_wait">请稍等…</string>
|
||||
<string name="txt_release_notes">版本说明</string>
|
||||
<string name="txt_firmware_name">固件名称</string>
|
||||
<string name="txt_firmware_size">固件大小</string>
|
||||
<string name="txt_down_firmware">下载固件</string>
|
||||
<string name="txt_dfu_model">进入DFU模式</string>
|
||||
<string name="txt_search_dfu">搜索DUF设备</string>
|
||||
<string name="txt_connect_device">连接设备</string>
|
||||
<string name="txt_reconnect_device">重连设备</string>
|
||||
<string name="txt_unconnect">设备已断开</string>
|
||||
<string name="txt_upgrading">升级中</string>
|
||||
<string name="txt_upgrade_start">准备升级</string>
|
||||
<string name="txt_device_connect_success">设备连接成功</string>
|
||||
<string name="txt_battery">电量</string>
|
||||
<string name="txt_january_abbr">1月</string>
|
||||
<string name="txt_february_abbr">2月</string>
|
||||
<string name="txt_march_abbr">3月</string>
|
||||
<string name="txt_april_abbr">4月</string>
|
||||
<string name="txt_may_abbr">5月</string>
|
||||
<string name="txt_june_abbr">6月</string>
|
||||
<string name="txt_july_abbr">7月</string>
|
||||
<string name="txt_august_abbr">8月</string>
|
||||
<string name="txt_september_abbr">9月</string>
|
||||
<string name="txt_october_abbr">10月</string>
|
||||
<string name="txt_november_abbr">11月</string>
|
||||
<string name="txt_december_abbr">12月</string>
|
||||
<string name="txt_minimum">最小值</string>
|
||||
<string name="txt_total_activity_distance">活动总距离</string>
|
||||
<string name="txt_welcome_back">欢迎回来</string>
|
||||
<string name="txt_mm_dd">月/年 (MM/YY)</string>
|
||||
<string name="txt_cvc">安全码 (CVC)</string>
|
||||
<string name="txt_enable">启用</string>
|
||||
<string name="txt_renew_year2">/年)</string>
|
||||
<string name="txt_save_power_tip">只要设备检测到您的爱宠处于WiFi区域内,就会关闭实时追踪以延长电池续航。</string>
|
||||
<string name="txt_invite_new">+邀请</string>
|
||||
<string name="txt_delete_pet_data1">这将从您的账户中永久删除所有</string>
|
||||
<string name="txt_delete_pet_data2">数据</string>
|
||||
<string name="txt_bluetooth_enabled">蓝牙</string>
|
||||
<string name="txt_search_device">正在搜索…</string>
|
||||
<string name="txt_7days_avg">7日均值</string>
|
||||
<string name="txt_weak_gps_signal">GPS信号弱</string>
|
||||
<string name="map_current_no_signal">无网络信号</string>
|
||||
<string name="txt_resting_time_uppercase">休息时间</string>
|
||||
<string name="txt_km_h">公里/小时 (km/h)</string>
|
||||
<string name="txt_mph">英里/小时 (mph)</string>
|
||||
<string name="txt_family_invitation_dec1">您的朋友</string>
|
||||
<string name="txt_family_invitation_dec2">邀请您成为</string>
|
||||
<string name="txt_family_invitation_dec3">的家人。</string>
|
||||
<string name="txt_auto_renew1">自动续费</string>
|
||||
<string name="txt_renewal_month1">续费:</string>
|
||||
<string name="txt_notifications_emergencies">告警日志</string>
|
||||
<string name="txt_family_sharing">家庭成员共享</string>
|
||||
<string name="txt_customer_support">30天退款保证</string>
|
||||
<string name="txt_show_crash">程序出现异常,即将退出</string>
|
||||
<string name="txt_powered_off">已关机</string>
|
||||
<string name="txt_load_more_pull_text">下拉加载更多</string>
|
||||
<string name="txt_load_more_release_text">释放加载</string>
|
||||
<string name="txt_total">总计</string>
|
||||
<string name="txt_show_all_pet">显示所有宠物</string>
|
||||
<string name="txt_use_valid_phone">请使用有效的手机号码</string>
|
||||
<string name="txt_use_valid_phone">请输入有效的电话号码</string>
|
||||
<string name="txt_account">账户</string>
|
||||
<string name="txt_3_months_includes">1. 灵活短期保障\n\n2. 30天退款保证</string>
|
||||
<string name="txt_1_year_includes">1. 专属客户支持\n\n2. 全年保障\n\n3. 30天退款保证</string>
|
||||
<string name="txt_2_years_includes">1. 免费设备更换(1次)\n\n2. 增强保障\n\n3. 宠物无忧保障\n\n4. 30天退款保证</string>
|
||||
<string name="tracker_number">%d个设备</string>
|
||||
<string name="pet_number">%d只</string>
|
||||
<string name="pet_manage_height">%d 英寸</string>
|
||||
<string name="txt_permissions_fail_tips">未能获得许可</string>
|
||||
<string name="no_pet">无宠物</string>
|
||||
<string name="no_bind_pet">请先绑定宠物</string>
|
||||
<string name="txt_battery_unit">%d%%</string>
|
||||
<string name="txt_pet_birthdayDate">%d年%d月</string>
|
||||
<string name="selector_folder_video_easy_photos">全部视频</string>
|
||||
<string name="selector_action_done_easy_photos">完成(%1$d/%2$d)</string>
|
||||
<string name="selector_reach_max_hint_easy_photos">最多支持%d个图片或视频</string>
|
||||
<string name="selector_reach_max_image_hint_easy_photos">最多支持%d个图片</string>
|
||||
<string name="selector_reach_max_video_hint_easy_photos">最多支持%d个视频</string>
|
||||
<string name="selector_image_size_error_easy_photos">照片的宽度应大于%1$d,高度应大于%1$d</string>
|
||||
<string name="permissions_again_easy_photos">请允许相关权限</string>
|
||||
<string name="permissions_die_easy_photos">请允许相关权限</string>
|
||||
<string name="preview_current_number_easy_photos">%1$d/%2$d</string>
|
||||
<string name="txt_today_date">今天\t%s</string>
|
||||
<string name="video_selection_easy_photos">选择视频</string>
|
||||
<string name="txt_dollar">¥\t%.2f</string>
|
||||
<string name="txt_goal_percent">%s%%</string>
|
||||
<string name="txt_reset_password_tips">输入您档案的注册邮箱,我们将发送4位数验证码至该邮箱</string>
|
||||
<string name="txt_money_unit">$%s</string>
|
||||
<string name="txt_per_month_money">$%s/月</string>
|
||||
<string name="txt_per_year_money">$%s/年</string>
|
||||
<string name="txt_delete_pet_data">这将从您的账户中永久删除所有 %s 数据</string>
|
||||
<string name="txt_renew_year">(按每年 $%s 续订)</string>
|
||||
<string name="txt_activity_success">激活成功!</string>
|
||||
<string name="txt_start_min_live">正在启动 %s-分钟直播</string>
|
||||
<string name="txt_code_valid_min">验证码有效期为 %ss</string>
|
||||
<string name="txt_family_invitation_dec">您的朋友 %s 邀请您成为 %s 的家人。</string>
|
||||
<string name="txt_renewal_year">续费:$%s/年,于%s</string>
|
||||
<string name="txt_renewal_month">续费:$%s/月,于%s</string>
|
||||
<string name="txt_annual_care">年度保险</string>
|
||||
<string name="txt_auto_subscription_year">(此后按每年 $%s 续订)</string>
|
||||
<string name="txt_auto_subscription_month">(此后按每月 $%s 续订)</string>
|
||||
<string name="txt_fail">失败</string>
|
||||
<string name="txt_edit_pay_method">编辑付款方式</string>
|
||||
<string name="txt_please_enter_pws">请输入密码。</string>
|
||||
<string name="txt_location_tip">ABBIDOT应用收集位置数据,可计算当前位置与设备之间的路线和距离。</string>
|
||||
<string name="txt_auto_subscription_day">(之后按$%s每天续费)</string>
|
||||
<string name="txt_auto_subscription_days">(之后按$%s/%s天续费)</string>
|
||||
<string name="txt_auto_subscription_years">(之后按$%s/%s年续费)</string>
|
||||
<string name="txt_auto_subscription_months">(之后按$%s/%s月续费)</string>
|
||||
<string name="txt_renewal_years">续订:$%s / %s 年,于 %s</string>
|
||||
<string name="txt_renewal_months">续订:$%s / %s 月,于 %s</string>
|
||||
<string name="txt_terms_html">terms_zh.html</string>
|
||||
<string name="txt_privacy_html">privacy_zh.html</string>
|
||||
<string name="txt_subscription_terms_conditions_html">subscription_terms_conditions_zh.html</string>
|
||||
<string name="txt_phone_has_bound">该手机号码已被绑定</string>
|
||||
|
||||
</resources>
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user