Commit 552c8ce0 authored by 马乐's avatar 马乐

1.完善单向可信数据源封装

parent 69f8a7a4
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
// id 'kotlin-kapt'
id 'com.google.dagger.hilt.android'
id 'kotlin-kapt'
}
android {
......@@ -16,6 +17,15 @@ android {
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField 'String','DEV_MAP_SOURCE_HOST','"http://192.168.9.152:9290/"'
buildConfigField 'String','TEST_MAP_SOURCE_HOST','"http://192.168.9.152:9290/"'
buildConfigField 'String','DEV_API_SERVER_HOST','"http://192.168.9.152:9290/"'
buildConfigField 'String','TEST_API_SERVER_HOST','"http://192.168.9.152:9290/"'
buildConfigField 'String','TEST_PLATFORM_ADDRESS','"http://192.168.9.152:9290/"'
buildConfigField 'String','DEV_PLATFORM_ADDRESS','"http://192.168.9.152:9290/"'
buildConfigField 'double','DEFAULT_LONGITUDE','119.7622539014'
buildConfigField 'double','DEFAULT_LATITUDE','49.3795031825'
}
buildTypes {
......@@ -42,29 +52,45 @@ android {
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
implementation 'androidx.core:core-ktx:1.10.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1'
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
implementation "androidx.room:room-runtime:2.5.0"
implementation "androidx.room:room-ktx:2.5.0"
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.10.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.moshi:moshi-kotlin:1.14.0'
implementation 'com.mapbox.maps:android:10.11.0'
implementation 'com.mapbox.mapboxsdk:mapbox-sdk-geojson:6.9.0'
implementation 'io.netty:netty-buffer:4.1.87.Final'
implementation 'io.github.toggery:jt808-codec:2.0.3'
implementation 'com.blankj:utilcodex:1.31.1'
implementation 'org.jetbrains.kotlin:kotlin-reflect:1.7.20'
implementation 'org.jetbrains.kotlin:kotlin-reflect:1.7.22'
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.2'
implementation 'com.github.mik3y:usb-serial-for-android:3.5.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'io.github.razerdp:BasePopup:3.2.1'
// implementation 'com.github.JessYanCoding:AndroidAutoSize:v1.2.1'
implementation 'com.google.android.exoplayer:exoplayer:2.17.1'
implementation 'com.afollestad.material-dialogs:core:3.2.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.0-RC'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.0-RC'
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
implementation "com.google.dagger:hilt-android:2.44"
kapt "com.google.dagger:hilt-compiler:2.44"
kapt "androidx.room:room-compiler:2.5.0"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
\ No newline at end of file
......@@ -16,12 +16,13 @@
<application
android:name=".MyApp"
android:name=".AntiCollisionApp"
android:allowBackup="true"
android:requestLegacyExternalStorage="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/waytous_logo"
android:networkSecurityConfig="@xml/network_security_config"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.HTAnticollision"
......
......@@ -5,13 +5,14 @@ import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.SPStaticUtils
import com.blankj.utilcode.util.SPUtils
import com.blankj.utilcode.util.Utils
import dagger.hilt.android.HiltAndroidApp
import kotlin.properties.Delegates
class MyApp: Application() {
@HiltAndroidApp
class AntiCollisionApp: Application(){
override fun onCreate() {
super.onCreate()
instance = this
Utils.init(this)
LogUtils.getConfig().globalTag = "Waytous"
SPStaticUtils.setDefaultSPUtils(SPUtils.getInstance("settings"))
......@@ -19,7 +20,7 @@ class MyApp: Application() {
companion object {
//情况一:声明可空的属性
private var instance: MyApp by Delegates.notNull()
private var instance: AntiCollisionApp by Delegates.notNull()
fun instance() = instance
}
}
\ No newline at end of file
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.waytous.anticollision
import android.os.Handler
import android.os.Looper
import java.util.concurrent.Executor
import java.util.concurrent.Executors
import javax.inject.Inject
import javax.inject.Singleton
/**
* Global executor pools for the whole application.
*
* Grouping tasks like this avoids the effects of task starvation (e.g. disk reads don't wait behind
* webservice requests).
*/
@Singleton
open class AppExecutors(
private val diskIO: Executor,
private val networkIO: Executor,
private val mainThread: Executor
) {
@Inject
constructor() : this(
Executors.newSingleThreadExecutor(),
Executors.newFixedThreadPool(3),
MainThreadExecutor()
)
fun diskIO(): Executor {
return diskIO
}
fun networkIO(): Executor {
return networkIO
}
fun mainThread(): Executor {
return mainThread
}
private class MainThreadExecutor : Executor {
private val mainThreadHandler = Handler(Looper.getMainLooper())
override fun execute(command: Runnable) {
mainThreadHandler.post(command)
}
}
}
package com.waytous.anticollision.api
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import com.waytous.anticollision.BuildConfig
import com.waytous.anticollision.bean.MapDataSource
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
interface ApiService {
/**
* 获取障碍物图层数据
* @param version
* */
@GET("api/map/obstaclesversion")
suspend fun obstaclesVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取电子围栏图层数据
* @param version
* */
@GET("api/map/electronicFenceversion")
suspend fun electronicFenceVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取湿滑区域图层数据
* @param version
* */
@GET("api/map/wetAreaversion")
suspend fun wetAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取车道节点图层数据
* @param version
* */
@GET("api/map/lanenodeversion")
suspend fun laneNodeVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取车道图层数据
* @param version
* */
@GET("api/map/laneversion")
suspend fun laneVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取可行使区域图层数据
* @param version
* */
@GET("api/map/runableareaversion")
suspend fun runnableAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取卸载区图层数据
* @param version
* */
@GET("api/map/dumpareaversion")
suspend fun dumpAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取装载区图层数据
* @param version
* */
@GET("api/map/diggingworkareaversion")
suspend fun diggingWorkAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取挡墙图层数据
* @param version
* */
@GET("api/map/barricadeversion")
suspend fun barricadeVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取静态区域图层数据
* @param version
* */
@GET("api/map/stationareaversion")
suspend fun stationAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取静态区域图层数据
* @param version
* */
@GET("api/map/staticobjsversion")
suspend fun staticObjectsVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取停车位图层数据
* @param version
* */
@GET("api/map/parkspotversion")
suspend fun parkSpotVersion(@Query("version") version:String = "-1"): MapDataSource?
companion object {
private val BASE_URL by lazy {
if (BuildConfig.DEBUG) BuildConfig.TEST_MAP_SOURCE_HOST else BuildConfig.DEV_MAP_SOURCE_HOST
}
private val moshi: Moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
fun create(): ApiService {
val logger = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC }
val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
.create(ApiService::class.java)
}
}
}
\ No newline at end of file
package com.waytous.anticollision.api
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import com.waytous.anticollision.BuildConfig
import com.waytous.anticollision.bean.MapDataSource
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
interface MapSourceService {
/**
* 获取障碍物图层数据
* @param version
* */
@GET("api/map/obstaclesversion")
suspend fun obstaclesVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取电子围栏图层数据
* @param version
* */
@GET("api/map/electronicFenceversion")
suspend fun electronicFenceVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取湿滑区域图层数据
* @param version
* */
@GET("api/map/wetAreaversion")
suspend fun wetAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取车道节点图层数据
* @param version
* */
@GET("api/map/lanenodeversion")
suspend fun laneNodeVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取车道图层数据
* @param version
* */
@GET("api/map/laneversion")
suspend fun laneVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取可行使区域图层数据
* @param version
* */
@GET("api/map/runableareaversion")
suspend fun runnableAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取卸载区图层数据
* @param version
* */
@GET("api/map/dumpareaversion")
suspend fun dumpAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取装载区图层数据
* @param version
* */
@GET("api/map/diggingworkareaversion")
suspend fun diggingWorkAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取挡墙图层数据
* @param version
* */
@GET("api/map/barricadeversion")
suspend fun barricadeVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取静态区域图层数据
* @param version
* */
@GET("api/map/stationareaversion")
suspend fun stationAreaVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取静态区域图层数据
* @param version
* */
@GET("api/map/staticobjsversion")
suspend fun staticObjectsVersion(@Query("version") version:String = "-1"): MapDataSource?
/**
* 获取停车位图层数据
* @param version
* */
@GET("api/map/parkspotversion")
suspend fun parkSpotVersion(@Query("version") version:String = "-1"): MapDataSource?
companion object {
private val BASE_URL by lazy {
if (BuildConfig.DEBUG) BuildConfig.TEST_MAP_SOURCE_HOST else BuildConfig.DEV_MAP_SOURCE_HOST
}
private val moshi: Moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
fun create(): MapSourceService {
val logger = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC }
val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
.create(MapSourceService::class.java)
}
}
}
\ No newline at end of file
package com.waytous.anticollision.bean
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.squareup.moshi.Json
/**
* 地图数据源
* @author male
* */
@Entity(tableName = "map_source")
data class MapDataSource(
/**数据源ID*/
@PrimaryKey
@ColumnInfo(name = "sourceId")
@Json(ignore = true)
var sourceId:String = "",
/**地图geojson数据*/
@ColumnInfo(name = "geojson")
@Json(name = "geojson")
val geojson: String = "",
/**地图geojson数据版本*/
@ColumnInfo(name = "version")
@Json(name = "version")
val version: Int = -1
)
\ No newline at end of file
package com.waytous.anticollision.bean
data class MapDataSourceWrapper(val mapDataSource: MapDataSource, val abort:Boolean)
\ No newline at end of file
package com.waytous.anticollision.database
import androidx.room.Database
import androidx.room.RoomDatabase
import com.waytous.anticollision.bean.MapDataSource
@Database(entities = [MapDataSource::class], version = 1, exportSchema = false)
abstract class AppDatabase: RoomDatabase() {
abstract fun mapDataSourceDao():MapDataDao
}
\ No newline at end of file
package com.waytous.anticollision.database
import androidx.room.*
import com.waytous.anticollision.bean.MapDataSource
@Dao
interface MapDataDao {
@Query("SELECT * FROM map_source WHERE sourceId = :sourceId")
suspend fun findById(sourceId:String):MapDataSource
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(vararg sources: MapDataSource)
@Delete
suspend fun deleteSource(source: MapDataSource)
}
\ No newline at end of file
package com.waytous.anticollision.location
import com.mapbox.common.LifecycleMonitoringState
import com.mapbox.common.LifecycleObserver
import com.mapbox.common.LifecycleState
import com.mapbox.maps.plugin.locationcomponent.LocationConsumer
import com.mapbox.maps.plugin.locationcomponent.LocationProvider
class MyLocationProvider:LocationProvider {
class MyLocationProvider:LocationProvider,LifecycleObserver{
override fun registerLocationConsumer(locationConsumer: LocationConsumer) {
TODO("Not yet implemented")
}
......@@ -11,4 +14,12 @@ class MyLocationProvider:LocationProvider {
override fun unRegisterLocationConsumer(locationConsumer: LocationConsumer) {
TODO("Not yet implemented")
}
override fun onMonitoringStateChanged(state: LifecycleMonitoringState, error: String?) {
TODO("Not yet implemented")
}
override fun onLifecycleStateChanged(state: LifecycleState) {
TODO("Not yet implemented")
}
}
\ No newline at end of file
package com.waytous.anticollision.repository
import android.content.Context
import androidx.room.Room
import com.blankj.utilcode.util.LogUtils
import com.waytous.anticollision.api.MapSourceService
import com.waytous.anticollision.bean.MapDataSourceWrapper
import com.waytous.anticollision.database.AppDatabase
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class MainRepository@Inject constructor(context:Context) {
private val mapApi by lazy {
MapSourceService.create()
}
private val mapDao by lazy {
Room.databaseBuilder(context,AppDatabase::class.java,"anti_collision.db")
.fallbackToDestructiveMigration().build()
.mapDataSourceDao()
}
fun remoteObstaclesVersion(version:String = "-1") = suspend { mapApi.obstaclesVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(OBSTACLES_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = OBSTACLES_SOURCE })
LogUtils.d("remoteObstaclesVersion")
MapDataSourceWrapper(it, true)
} else {
LogUtils.d("remoteObstaclesVersion")
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的障碍物图层数据为空!")
}
}
fun localObstaclesVersion() = flow {
val source = mapDao.findById(OBSTACLES_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
fun remoteElectronicFenceVersion(version:String = "-")= suspend { mapApi.electronicFenceVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(ELECTRONIC_FENCE_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = ELECTRONIC_FENCE_SOURCE })
MapDataSourceWrapper(it, true)
} else {
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的电子围栏地图数据为空!")
}
}
fun localElectronicFenceVersion() = flow {
val source = mapDao.findById(ELECTRONIC_FENCE_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
fun remoteWetAreaVersion(version:String = "-1")= suspend { mapApi.wetAreaVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(WET_AREA_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = WET_AREA_SOURCE })
MapDataSourceWrapper(it, true)
} else {
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的湿滑区域地图数据为空!")
}
}
fun localWetAreaVersion() = flow {
val source = mapDao.findById(WET_AREA_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
fun remoteLaneNodeVersion(version:String = "-1")= suspend { mapApi.laneNodeVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(LANE_NODE_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = LANE_NODE_SOURCE })
MapDataSourceWrapper(it, true)
} else {
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的车道节点地图数据为空!")
}
}
fun localLaneNodeVersion() = flow {
val source = mapDao.findById(LANE_NODE_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
fun remoteLaneVersion(version:String = "-1")= suspend { mapApi.laneVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(LANE_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = LANE_SOURCE })
MapDataSourceWrapper(it, true)
} else {
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的车道图层地图数据为空!")
}
}
fun localLaneVersion() = flow {
val source = mapDao.findById(LANE_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
fun remoteRunnableAreaVersion(version:String = "-1")= suspend { mapApi.runnableAreaVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(RUNNABLE_AREA_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = RUNNABLE_AREA_SOURCE })
MapDataSourceWrapper(it, true)
} else {
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的可行使区域地图数据为空!")
}
}
fun localRunnableAreaVersion() = flow {
val source = mapDao.findById(RUNNABLE_AREA_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
fun remoteDumpAreaVersion(version:String = "-1")= suspend { mapApi.dumpAreaVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(DUMP_AREA_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = DUMP_AREA_SOURCE })
MapDataSourceWrapper(it, true)
} else {
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的卸载区地图数据为空!")
}
}
fun localDumpAreaVersion() = flow {
val source = mapDao.findById(DUMP_AREA_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
fun remoteDiggingWorkAreaVersion(version:String = "-1")= suspend { mapApi.diggingWorkAreaVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(DIGGING_WORK_AREA_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = DIGGING_WORK_AREA_SOURCE })
MapDataSourceWrapper(it, true)
} else {
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的装载区地图数据为空!")
}
}
fun localDiggingAreaVersion() = flow {
val source = mapDao.findById(DIGGING_WORK_AREA_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
fun remoteBarricadeVersion(version:String = "-1")= suspend { mapApi.barricadeVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(BARRICADE_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = BARRICADE_SOURCE })
MapDataSourceWrapper(it, true)
} else {
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的挡墙区域地图数据为空!")
}
}
fun localBarricadeVersion() = flow {
val source = mapDao.findById(BARRICADE_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
fun remoteStationAreaVersion(version:String = "-1")= suspend { mapApi.stationAreaVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(STATION_AREA_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = STATION_AREA_SOURCE })
MapDataSourceWrapper(it, true)
} else {
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的静态区域地图数据为空!")
}
}
fun localStationAreaVersion() = flow {
val source = mapDao.findById(STATION_AREA_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
fun remoteParkSpotVersion(version:String = "-1")= suspend { mapApi.parkSpotVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(PARK_SPOT_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = PARK_SPOT_SOURCE })
MapDataSourceWrapper(it, true)
} else {
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的停车位图层地图数据为空!")
}
}
fun localParkSpotVersion() = flow {
val source = mapDao.findById(PARK_SPOT_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
fun remoteStaticObjectsVersion(version:String = "-1")= suspend { mapApi.staticObjectsVersion(version) }
.asFlow()
.map {
if (it != null) {
val tempSource = mapDao.findById(STATIC_OBJECTS_SOURCE)
if (tempSource.version != it.version) {
mapDao.deleteSource(tempSource)
mapDao.insertAll(it.apply { sourceId = STATIC_OBJECTS_SOURCE })
MapDataSourceWrapper(it, true)
} else {
MapDataSourceWrapper(it, false)
}
} else {
throw Exception("获取到的静态区域地图数据为空!")
}
}
fun localStaticObjectsVersion() = flow {
val source = mapDao.findById(STATIC_OBJECTS_SOURCE)
emit( MapDataSourceWrapper(source, false))
}
companion object {
private const val DUMP_AREA_SOURCE = "dumpAreaSource"
private const val OBSTACLES_SOURCE = "obstaclesSource"
private const val ELECTRONIC_FENCE_SOURCE = "electronicFenceSource"
private const val WET_AREA_SOURCE = "wetAreaSource"
private const val LANE_NODE_SOURCE = "laneNodeSource"
private const val LANE_SOURCE = "laneSource"
private const val RUNNABLE_AREA_SOURCE = "runnableAreaSource"
private const val DIGGING_WORK_AREA_SOURCE = "diggingWorkAreaSource"
private const val BARRICADE_SOURCE = "barricadeSource"
private const val STATION_AREA_SOURCE = "stationAreaSource"
private const val STATIC_OBJECTS_SOURCE = "staticObjectsSource"
private const val PARK_SPOT_SOURCE = "parkSpotSource"
}
}
\ No newline at end of file
package com.waytous.anticollision.ui
import android.graphics.Bitmap
import android.graphics.Color
import android.os.Bundle
import androidx.core.graphics.scale
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.withStarted
import com.mapbox.geojson.Point
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.MapView
import com.mapbox.maps.extension.style.expressions.dsl.generated.get
import com.mapbox.maps.extension.style.layers.generated.circleLayer
import com.mapbox.maps.extension.style.layers.generated.fillLayer
import com.mapbox.maps.extension.style.layers.generated.lineLayer
import com.mapbox.maps.extension.style.layers.generated.symbolLayer
import com.mapbox.maps.extension.style.layers.properties.generated.*
import com.mapbox.maps.extension.style.sources.generated.geoJsonSource
import com.mapbox.maps.extension.style.style
import com.mapbox.maps.plugin.annotation.annotations
import com.mapbox.maps.plugin.annotation.generated.PointAnnotation
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationOptions
import com.mapbox.maps.plugin.annotation.generated.createPointAnnotationManager
import com.mapbox.maps.viewannotation.ViewAnnotationManager
import com.waytous.anticollision.R
import com.waytous.anticollision.api.ApiService
import com.waytous.anticollision.repository.MainRepository
import com.waytous.anticollision.utils.getBitmapFromVectorDrawable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
open class BaseFragment : Fragment() {
private val mapModel: MainViewModel by viewModels{
MainViewModel.MainViewModelFactory(MainRepository(requireContext()))
}
private lateinit var viewAnnotationManager: ViewAnnotationManager
private lateinit var pointAnnotationManager: PointAnnotationManager
private lateinit var pointAnnotation: PointAnnotation
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
fun updateMapBox(mapView:MapView){
mapView.getMapboxMap().setCamera(
CameraOptions.Builder().center(
Point.fromLngLat(
MainViewModel.LONGITUDE,
MainViewModel.LATITUDE
)).zoom(14.0).build()
)
lifecycleScope.launch{
withContext(Dispatchers.IO){
val apiService = ApiService.create()
val runnableAreaSource = apiService.runnableAreaVersion("-1")
val laneSource = apiService.laneVersion("-1")
val laneNodeSource = apiService.laneNodeVersion("-1")
val diggingWorkAreaSource = apiService.diggingWorkAreaVersion("-1")
val obstaclesSource = apiService.obstaclesVersion("-1")
val electronicFenceSource = apiService.electronicFenceVersion("-1")
val dumpAreaSource = apiService.dumpAreaVersion("-1")
val staticObjectsSource = apiService.staticObjectsVersion("-1")
val stationAreaSource = apiService.stationAreaVersion("-1")
val barricadeSource = apiService.barricadeVersion("-1")
val parkSpotSource = apiService.parkSpotVersion("-1")
val wetAreaSource = apiService.wetAreaVersion("-1")
withStarted {
mapView.getMapboxMap().loadStyle(
style(styleUri = MainViewModel.MY_MAP_BOX_STYLE) {
+geoJsonSource(MainViewModel.RUNNABLE_AREA_SOURCE) {
data(runnableAreaSource!!.geojson)
+fillLayer(
MainViewModel.RUNNABLE_AREA_LAYER,
MainViewModel.RUNNABLE_AREA_SOURCE
){
fillColor("#98a0a0")
fillOpacity(0.85)
fillOutlineColor("#FFFF00")
visibility(Visibility.VISIBLE)
}
}
+geoJsonSource(MainViewModel.LANE_SOURCE) {
data(laneSource!!.geojson)
+lineLayer(
MainViewModel.LANE_LAYER,
MainViewModel.LANE_SOURCE
){
lineColor("white")
lineWidth(3.0)
lineJoin(LineJoin.ROUND)
lineCap(LineCap.ROUND)
visibility(Visibility.VISIBLE)
}
}
+geoJsonSource(MainViewModel.STATIC_OBJECTS_SOURCE) {
data(staticObjectsSource!!.geojson)
+fillLayer(
MainViewModel.STATIC_OBJECTS_LAYER,
MainViewModel.STATIC_OBJECTS_SOURCE
){
fillColor("#98a0a0")
fillOpacity(0.85)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
+symbolLayer(MainViewModel.STATIC_OBJECTS_TEXT_LAYER, MainViewModel.STATIC_OBJECTS_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
+geoJsonSource(MainViewModel.DIGGING_WORK_AREA_SOURCE) {
data(diggingWorkAreaSource!!.geojson)
+fillLayer(
MainViewModel.DIGGING_WORK_AREA_LAYER,
MainViewModel.DIGGING_WORK_AREA_SOURCE
){
fillColor("#886e26")
fillOpacity(0.85)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
+symbolLayer(MainViewModel.DIGGING_WORK_AREA_TEXT_LAYER, MainViewModel.DIGGING_WORK_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
+geoJsonSource(MainViewModel.BARRICADE_SOURCE) {
data(barricadeSource!!.geojson)
+lineLayer(
MainViewModel.BARRICADE_LAYER,
MainViewModel.BARRICADE_SOURCE
){
lineColor("blue")
lineWidth(4.0)
lineJoin(LineJoin.ROUND)
lineCap(LineCap.ROUND)
visibility(Visibility.VISIBLE)
}
}
+geoJsonSource(MainViewModel.OBSTACLES_SOURCE) {
data(obstaclesSource!!.geojson)
+fillLayer(
MainViewModel.OBSTACLES_LAYER,
MainViewModel.OBSTACLES_SOURCE
){
fillColor("#6f9bdd")
fillOpacity(0.8)
visibility(Visibility.VISIBLE)
}
+symbolLayer(MainViewModel.OBSTACLES_TEXT_LAYER, MainViewModel.OBSTACLES_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
+geoJsonSource(MainViewModel.STATION_AREA_SOURCE) {
data(stationAreaSource!!.geojson)
+fillLayer(
MainViewModel.STATION_AREA_LAYER,
MainViewModel.STATION_AREA_SOURCE
){
fillColor("lightgreen")
fillOpacity(0.8)
visibility(Visibility.VISIBLE)
}
+symbolLayer(MainViewModel.STATION_AREA_TEXT_LAYER, MainViewModel.STATION_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxWidth(10.0)
}
}
+geoJsonSource(MainViewModel.LANE_NODE_SOURCE) {
data(laneNodeSource!!.geojson)
+circleLayer(
MainViewModel.LANE_NODE_LAYER,
MainViewModel.LANE_NODE_SOURCE
){
circleColor("red")
circleRadius(6.0)
visibility(Visibility.VISIBLE)
}
+symbolLayer(MainViewModel.LANE_TEXT_LAYER, MainViewModel.LANE_NODE_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(9.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
+geoJsonSource(MainViewModel.PARK_SPOT_SOURCE) {
data(parkSpotSource!!.geojson)
+fillLayer(
MainViewModel.PARK_SPOT_LAYER,
MainViewModel.PARK_SPOT_SOURCE
){
fillColor(get("#7e8185"))
fillOpacity(0.8)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
+symbolLayer(MainViewModel.PARK_SPOT_TEXT_LAYER, MainViewModel.PARK_SPOT_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(9.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
+geoJsonSource(MainViewModel.ELECTRONIC_FENCE_SOURCE) {
data(electronicFenceSource!!.geojson)
+fillLayer(
MainViewModel.ELECTRONIC_FENCE_LAYER,
MainViewModel.ELECTRONIC_FENCE_SOURCE
){
fillColor(get("color"))
fillOpacity(0.85)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
+symbolLayer(MainViewModel.ELECTRONIC_FENCE_TEXT_LAYER, MainViewModel.ELECTRONIC_FENCE_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
+geoJsonSource(MainViewModel.WET_AREA_SOURCE) {
data(wetAreaSource!!.geojson)
+fillLayer(
MainViewModel.WET_AREA_LAYER,
MainViewModel.WET_AREA_SOURCE
){
fillColor(get("color"))
fillOpacity(0.8)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
+symbolLayer(MainViewModel.WET_AREA_TEXT_LAYER, MainViewModel.WET_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
+geoJsonSource(MainViewModel.DUMP_AREA_SOURCE) {
data(dumpAreaSource!!.geojson)
+fillLayer(
MainViewModel.DUMP_AREA_LAYER,
MainViewModel.DUMP_AREA_SOURCE
){
fillColor("#886e26")
fillOpacity(0.85)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
+symbolLayer(MainViewModel.DUMP_AREA_TEXT_LAYER, MainViewModel.DUMP_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
+geoJsonSource("truckPathSource") {
data("{ \"type\": \"FeatureCollection\", \"features\":[]}")
+lineLayer(
"truckPathLayer",
"truckPathSource"
){
lineColor("green")
lineWidth(8.0)
lineOpacity(0.8)
lineJoin(LineJoin.ROUND)
lineCap(LineCap.ROUND)
visibility(Visibility.VISIBLE)
}
}
}
){
val bitmap: Bitmap? =
activity?.getBitmapFromVectorDrawable(R.drawable.my_vehicle_normal, 4)
val annotationPlugin = mapView.annotations
val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
.withPoint(mapModel.center.value!!)
.withIconImage(bitmap!!.apply {
scale(bitmap.width / 4, bitmap.height / 4)
})
.withIconAnchor(IconAnchor.BOTTOM)
.withDraggable(false)
pointAnnotationManager = annotationPlugin.createPointAnnotationManager()
pointAnnotation = pointAnnotationManager.create(pointAnnotationOptions)
}
}
}
}
}
}
\ No newline at end of file
......@@ -2,16 +2,22 @@ package com.waytous.anticollision.ui
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import com.blankj.utilcode.util.BarUtils
import com.blankj.utilcode.util.ColorUtils
import com.gyf.immersionbar.ImmersionBar
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.ActivityMainBinding
import com.waytous.anticollision.repository.MainRepository
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val viewModel by lazy {
ViewModelProvider(this,MainViewModel.MainViewModelFactory(MainRepository(this)))[MainViewModel::class.java]
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//设置下布局向上移动状态栏的高度
......
package com.waytous.anticollision.ui
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.CreationExtras
import com.mapbox.geojson.Point
import com.waytous.anticollision.repository.MainRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import java.math.BigDecimal
import javax.inject.Inject
class MainViewModel @Inject constructor(private val mainRepository: MainRepository) : ViewModel() {
val zoom: MutableLiveData<BigDecimal> by lazy {
MutableLiveData(BigDecimal(16.0))
}
val center: MutableLiveData<Point> by lazy {
MutableLiveData(Point.fromLngLat(LONGITUDE, LATITUDE))
}
fun obstaclesSource() =
flowOf(mainRepository.localObstaclesVersion(), mainRepository.remoteObstaclesVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
fun electronicFenceSource() = flowOf(
mainRepository.localElectronicFenceVersion(),
mainRepository.remoteElectronicFenceVersion()
)
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
fun wetAreaSource() =
flowOf(mainRepository.localWetAreaVersion(), mainRepository.remoteWetAreaVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
fun laneNodeSource() =
flowOf(mainRepository.localLaneNodeVersion(), mainRepository.remoteLaneNodeVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
fun laneSource() = flowOf(mainRepository.localLaneVersion(), mainRepository.remoteLaneVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
fun runnableAreaSource() = flowOf(
mainRepository.localRunnableAreaVersion(),
mainRepository.remoteRunnableAreaVersion()
).flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
fun dumpAreaSource() =
flowOf(mainRepository.localDumpAreaVersion(), mainRepository.remoteDumpAreaVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
fun diggingWorkAreaSource() = flowOf(
mainRepository.localDiggingAreaVersion(),
mainRepository.remoteDiggingWorkAreaVersion()
).flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
fun barricadeSource() =
flowOf(mainRepository.localBarricadeVersion(), mainRepository.remoteBarricadeVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
fun stationAreaSource() =
flowOf(mainRepository.localStationAreaVersion(), mainRepository.remoteStationAreaVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
fun parkSpotSource() =
flowOf(mainRepository.localParkSpotVersion(), mainRepository.remoteParkSpotVersion())
.flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
fun staticObjectsSource() = flowOf(
mainRepository.localStaticObjectsVersion(),
mainRepository.remoteStaticObjectsVersion()
).flattenMerge()
.transformWhile {
emit(it.mapDataSource)
!it.abort
}.map {
it.geojson
}.flowOn(Dispatchers.IO)
.catch {
emit("")
}
companion object {
const val MY_MAP_BOX_STYLE = "asset://style.json"
const val DUMP_AREA_SOURCE = "dumpAreaSource"
const val DUMP_AREA_LAYER = "dumpAreaLayer"
const val DUMP_AREA_TEXT_LAYER = "dumpAreaTextLayer"
const val OBSTACLES_SOURCE = "obstaclesSource"
const val OBSTACLES_LAYER = "obstaclesLayer"
const val OBSTACLES_TEXT_LAYER = "obstaclesTextLayer"
const val ELECTRONIC_FENCE_SOURCE = "electronicFenceSource"
const val ELECTRONIC_FENCE_LAYER = "electronicFenceLayer"
const val ELECTRONIC_FENCE_TEXT_LAYER = "electronicFenceTextLayer"
const val WET_AREA_SOURCE = "wetAreaSource"
const val WET_AREA_LAYER = "wetAreaLayer"
const val WET_AREA_TEXT_LAYER = "wetAreaTextLayer"
const val LANE_NODE_SOURCE = "laneNodeSource"
const val LANE_NODE_LAYER = "laneNodeLayer"
const val LANE_NODE_TEXT_LAYER = "laneNodeTextLayer"
const val LANE_SOURCE = "laneSource"
const val LANE_LAYER = "laneLayer"
const val LANE_TEXT_LAYER = "laneTextLayer"
const val RUNNABLE_AREA_SOURCE = "runnableAreaSource"
const val RUNNABLE_AREA_LAYER = "runnableAreaLayer"
const val RUNNABLE_AREA_TEXT_LAYER = "runnableAreaTextLayer"
const val DIGGING_WORK_AREA_SOURCE = "diggingWorkAreaSource"
const val DIGGING_WORK_AREA_LAYER = "diggingWorkAreaLayer"
const val DIGGING_WORK_AREA_TEXT_LAYER = "diggingWorkAreaTextLayer"
const val BARRICADE_SOURCE = "barricadeSource"
const val BARRICADE_LAYER = "barricadeLayer"
const val BARRICADE_TEXT_LAYER = "barricadeTextLayer"
const val STATION_AREA_SOURCE = "stationAreaSource"
const val STATION_AREA_LAYER = "stationAreaLayer"
const val STATION_AREA_TEXT_LAYER = "stationAreaTextLayer"
const val STATIC_OBJECTS_SOURCE = "staticObjectsSource"
const val STATIC_OBJECTS_LAYER = "staticObjectsLayer"
const val STATIC_OBJECTS_TEXT_LAYER = "staticObjectsTextLayer"
const val PARK_SPOT_SOURCE = "parkSpotSource"
const val PARK_SPOT_LAYER = "parkSpotLayer"
const val PARK_SPOT_TEXT_LAYER = "parkSpotTextLayer"
const val LONGITUDE = 119.7622539014
const val LATITUDE = 49.3795031825
const val ZOOM = 16.0
}
class MainViewModelFactory(private val mainRepository: MainRepository) :
ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
return MainViewModel(mainRepository) as T
}
}
}
\ No newline at end of file
package com.waytous.anticollision.ui
import android.content.Context
import android.graphics.Color
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import com.blankj.utilcode.util.LogUtils
import com.mapbox.geojson.Point
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.MapView
import com.mapbox.maps.MapboxMap
import com.mapbox.maps.Style
import com.mapbox.maps.extension.style.expressions.dsl.generated.get
import com.mapbox.maps.extension.style.layers.generated.circleLayer
import com.mapbox.maps.extension.style.layers.generated.fillLayer
import com.mapbox.maps.extension.style.layers.generated.lineLayer
import com.mapbox.maps.extension.style.layers.generated.symbolLayer
import com.mapbox.maps.extension.style.layers.properties.generated.*
import com.mapbox.maps.extension.style.projection.generated.projection
import com.mapbox.maps.extension.style.sources.addSource
import com.mapbox.maps.extension.style.sources.generated.geoJsonSource
import com.mapbox.maps.extension.style.style
import com.mapbox.maps.plugin.animation.flyTo
import com.mapbox.maps.plugin.attribution.attribution
import com.mapbox.maps.plugin.compass.compass
import com.mapbox.maps.plugin.logo.logo
import com.waytous.anticollision.BuildConfig
import com.waytous.anticollision.R
/**
* mapbox及控制组件封装
* @author male
* @param context
* @param attributeSet
* */
class MapBoxLayout(context: Context, private val attributeSet: AttributeSet):FrameLayout(context,attributeSet) {
/**
* mapbox地图
* */
private var mapView:MapView
/**
* mapbox
* */
private var mapBox:MapboxMap
/**
* sos按钮
* */
private var sosButton: AppCompatImageView
/**
* 急停按钮
* */
private var emergency: AppCompatImageView
/**
* 放大按钮
* */
private var zoomOut: AppCompatImageView
/**
* 缩小按钮
* */
private var zoomIn: AppCompatImageView
/**
* 定位车辆位置
* */
private var locationTruck: AppCompatImageView
/**
* 关闭&显示安全距离
* */
private var toggleSafetyRange: AppCompatImageView
/**
* 地图采集信息文本
* */
private var collectDataText:AppCompatTextView
private var cameraOptions:CameraOptions
private var zoomLevel:Double = 14.0
private lateinit var style: Style
companion object{
private val scaleLengths = listOf(5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000, 2000000)
private const val MINIMUM_ZOOM_LEVEL = 11.0
private const val MAXIMUM_ZOOM_LEVEL = 26.0
}
init {
val root:View = LayoutInflater.from(context).inflate(R.layout.layout_map_box,this,true)
mapView = root.findViewById<MapView>(R.id.mapView).also {
it.logo.enabled = false
it.compass.enabled = false
it.attribution.enabled = false
}
mapBox = mapView.getMapboxMap().also {mapbox ->
mapbox.loadStyle(style(MainViewModel.MY_MAP_BOX_STYLE){
+projection(ProjectionName.GLOBE)
}){
style = it
addTruckPathSource()
}
}
cameraOptions = CameraOptions.Builder().center(Point.fromLngLat(BuildConfig.DEFAULT_LONGITUDE,BuildConfig.DEFAULT_LATITUDE)).zoom(zoomLevel).build()
sosButton = root.findViewById<AppCompatImageView?>(R.id.sos).also {
it.setOnClickListener {
}
}
emergency = root.findViewById(R.id.emergency)
zoomOut = root.findViewById<AppCompatImageView?>(R.id.zoomOut).also {
it.setOnClickListener {
}
}
zoomIn = root.findViewById<AppCompatImageView?>(R.id.zoomIn).also {
}
locationTruck = root.findViewById<AppCompatImageView?>(R.id.locationTruck).also {
}
toggleSafetyRange = root.findViewById<AppCompatImageView?>(R.id.toggleSafetyRange).also {
}
collectDataText = root.findViewById(R.id.collectDataText)
}
fun updateCenter(center:Point){
mapBox.flyTo(cameraOptions.toBuilder().center(center).build())
}
private fun calculateScale(){
}
fun addRunnableAreaSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.RUNNABLE_AREA_SOURCE) {
data(source)
}
fillLayer(
MainViewModel.RUNNABLE_AREA_LAYER,
MainViewModel.RUNNABLE_AREA_SOURCE
){
fillColor("#98a0a0")
fillOpacity(0.85)
fillOutlineColor("#FFFF00")
visibility(Visibility.VISIBLE)
}
}
}
fun addLaneSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.LANE_SOURCE) {
data(source)
}
lineLayer(
MainViewModel.LANE_LAYER,
MainViewModel.LANE_SOURCE
){
lineColor("white")
lineWidth(3.0)
lineJoin(LineJoin.ROUND)
lineCap(LineCap.ROUND)
visibility(Visibility.VISIBLE)
}
}
}
fun addStaticObjectsSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.STATIC_OBJECTS_SOURCE) {
data(source)
}
fillLayer(
MainViewModel.STATIC_OBJECTS_LAYER,
MainViewModel.STATIC_OBJECTS_SOURCE
){
fillColor("#98a0a0")
fillOpacity(0.85)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
symbolLayer(MainViewModel.STATIC_OBJECTS_TEXT_LAYER, MainViewModel.STATIC_OBJECTS_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
}
fun addDiggingWorkAreaSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.DIGGING_WORK_AREA_SOURCE) {
data(source)
}
fillLayer(
MainViewModel.DIGGING_WORK_AREA_LAYER,
MainViewModel.DIGGING_WORK_AREA_SOURCE
){
fillColor("#886e26")
fillOpacity(0.85)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
symbolLayer(MainViewModel.DIGGING_WORK_AREA_TEXT_LAYER, MainViewModel.DIGGING_WORK_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
}
fun addBarricadeSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.BARRICADE_SOURCE) {
data(source)
}
lineLayer(
MainViewModel.BARRICADE_LAYER,
MainViewModel.BARRICADE_SOURCE
){
lineColor("blue")
lineWidth(4.0)
lineJoin(LineJoin.ROUND)
lineCap(LineCap.ROUND)
visibility(Visibility.VISIBLE)
}
}
}
fun addObstaclesSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.OBSTACLES_SOURCE) {
data(source)
}
fillLayer(
MainViewModel.OBSTACLES_LAYER,
MainViewModel.OBSTACLES_SOURCE
){
fillColor("#6f9bdd")
fillOpacity(0.8)
visibility(Visibility.VISIBLE)
}
symbolLayer(MainViewModel.OBSTACLES_TEXT_LAYER, MainViewModel.OBSTACLES_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
}
fun addStationAreaSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.STATION_AREA_SOURCE) {
data(source)
}
fillLayer(
MainViewModel.STATION_AREA_LAYER,
MainViewModel.STATION_AREA_SOURCE
){
fillColor("lightgreen")
fillOpacity(0.8)
visibility(Visibility.VISIBLE)
}
symbolLayer(MainViewModel.STATION_AREA_TEXT_LAYER, MainViewModel.STATION_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxWidth(10.0)
}
}
}
fun addLaneNodeSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.LANE_NODE_SOURCE) {
data(source)
}
circleLayer(
MainViewModel.LANE_NODE_LAYER,
MainViewModel.LANE_NODE_SOURCE
){
circleColor("red")
circleRadius(6.0)
visibility(Visibility.VISIBLE)
}
symbolLayer(MainViewModel.LANE_TEXT_LAYER, MainViewModel.LANE_NODE_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(9.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
}
fun addParkSpotSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.PARK_SPOT_SOURCE) {
data(source)
}
fillLayer(
MainViewModel.PARK_SPOT_LAYER,
MainViewModel.PARK_SPOT_SOURCE
){
fillColor(get("#7e8185"))
fillOpacity(0.8)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
symbolLayer(MainViewModel.PARK_SPOT_TEXT_LAYER, MainViewModel.PARK_SPOT_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(9.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
}
fun addElectronicFenceSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.ELECTRONIC_FENCE_SOURCE) {
data(source)
}
fillLayer(
MainViewModel.ELECTRONIC_FENCE_LAYER,
MainViewModel.ELECTRONIC_FENCE_SOURCE
){
fillColor(get("color"))
fillOpacity(0.85)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
symbolLayer(MainViewModel.ELECTRONIC_FENCE_TEXT_LAYER, MainViewModel.ELECTRONIC_FENCE_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
}
fun addWetAreaSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.WET_AREA_SOURCE) {
data(source)
}
fillLayer(
MainViewModel.WET_AREA_LAYER,
MainViewModel.WET_AREA_SOURCE
){
fillColor(get("color"))
fillOpacity(0.8)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
symbolLayer(MainViewModel.WET_AREA_TEXT_LAYER, MainViewModel.WET_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
}
fun addDumpAreaSource(source: String){
style.addSource{
geoJsonSource(MainViewModel.DUMP_AREA_SOURCE) {
data(source)
}
fillLayer(
MainViewModel.DUMP_AREA_LAYER,
MainViewModel.DUMP_AREA_SOURCE
){
fillColor("#886e26")
fillOpacity(0.85)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
symbolLayer(MainViewModel.DUMP_AREA_TEXT_LAYER, MainViewModel.DUMP_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,-0.5))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
}
private fun addTruckPathSource(){
style.addSource{
geoJsonSource("truckPathSource") {
data("{ \"type\": \"FeatureCollection\", \"features\":[]}")
}
lineLayer(
"truckPathLayer",
"truckPathSource"
){
lineColor("green")
lineWidth(8.0)
lineOpacity(0.8)
lineJoin(LineJoin.ROUND)
lineCap(LineCap.ROUND)
visibility(Visibility.VISIBLE)
}
}
}
fun formatCollectionData(text:String){
val tagSpan = ForegroundColorSpan(Color.parseColor("#666666"))
val contentSpan = ForegroundColorSpan(Color.parseColor("#000000"))
val spannableString = SpannableString(text)
spannableString.setSpan(tagSpan, 0, 4, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
val textPointIndex = text.indexOf("采集点数")
spannableString.setSpan(contentSpan, 5, textPointIndex, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
spannableString.setSpan(tagSpan, textPointIndex, textPointIndex+4, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
val textPositionIndex = text.indexOf("当前位置")
spannableString.setSpan(contentSpan, textPointIndex+1, textPositionIndex, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
spannableString.setSpan(tagSpan, textPositionIndex, textPositionIndex+4, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
val textAltitudeIndex = text.indexOf("高程")
spannableString.setSpan(contentSpan, textPositionIndex+1, textAltitudeIndex, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
spannableString.setSpan(tagSpan, textAltitudeIndex, textAltitudeIndex+2, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
collectDataText.text = spannableString
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
}
}
\ No newline at end of file
......@@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.afollestad.materialdialogs.MaterialDialog
import com.blankj.utilcode.util.LogUtils
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
......@@ -23,13 +24,18 @@ class CollectFragment : Fragment() {
private val binding get() = _binding!!
private lateinit var dialogFaultCause:MaterialDialog
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
): View {
_binding = FragmentCollectBinding.inflate(inflater, container, false)
context?:return binding.root
initTablayout()
MaterialDialog(context!!).show {
setContentView(R.layout.dialog_fault_cause_select)
}
return binding.root
}
......
......@@ -6,41 +6,56 @@ import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.fragment.app.viewModels
import androidx.lifecycle.*
import com.blankj.utilcode.util.LogUtils
import com.mapbox.geojson.Point
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.MapView
import com.mapbox.maps.MapboxMap
import com.mapbox.maps.Style
import com.mapbox.maps.extension.observable.eventdata.MapLoadingErrorEventData
import com.mapbox.maps.extension.style.sources.generated.geoJsonSource
import com.mapbox.maps.extension.style.style
import com.mapbox.maps.plugin.Plugin
import com.mapbox.maps.plugin.annotation.annotations
import com.mapbox.maps.plugin.annotation.generated.CircleAnnotationOptions
import com.mapbox.maps.plugin.annotation.generated.createCircleAnnotationManager
import com.mapbox.maps.plugin.delegates.listeners.OnMapLoadErrorListener
import com.mapbox.maps.plugin.logo.LogoPlugin
import com.mapbox.maps.plugin.annotation.generated.PointAnnotation
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager
import com.mapbox.maps.plugin.attribution.attribution
import com.mapbox.maps.plugin.compass.compass
import com.mapbox.maps.plugin.logo.logo
import com.mapbox.maps.viewannotation.ViewAnnotationManager
import com.waytous.anticollision.R
import com.waytous.anticollision.databinding.FragmentHomeBinding
import com.waytous.anticollision.repository.MainRepository
import com.waytous.anticollision.ui.BaseFragment
import com.waytous.anticollision.ui.MainViewModel
import com.waytous.anticollision.ui.view.MoreFeaturesPopup
import com.waytous.anticollision.ui.view.WorkStatusEditPopup
import com.waytous.anticollision.utils.setTextSize
import kotlinx.coroutines.launch
class HomeFragment : Fragment() {
class HomeFragment : BaseFragment() {
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
private lateinit var mapView: MapView
private lateinit var mapBox:MapboxMap
private lateinit var viewAnnotationManager: ViewAnnotationManager
private lateinit var pointAnnotationManager: PointAnnotationManager
private lateinit var pointAnnotation: PointAnnotation
private lateinit var moreFeaturesPopup: MoreFeaturesPopup
private lateinit var workStatusEditPopup: WorkStatusEditPopup
private val mapModel: MainViewModel by viewModels{
MainViewModel.MainViewModelFactory(MainRepository(requireContext()))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
......@@ -48,7 +63,6 @@ class HomeFragment : Fragment() {
): View {
val homeViewModel =
ViewModelProvider(this)[HomeViewModel::class.java]
_binding = FragmentHomeBinding.inflate(inflater, container, false)
context?:return binding.root
workStatusEditPopup = WorkStatusEditPopup(context).also {
......@@ -62,27 +76,13 @@ class HomeFragment : Fragment() {
it.maskOffsetY = 20
it.setBackgroundColor(R.color.color_99000000)
}
val mapView: MapView = binding.defaultMapLayout.mapView
val logoPlugin = mapView.getPlugin<LogoPlugin>(Plugin.MAPBOX_LOGO_PLUGIN_ID)
logoPlugin?.enabled = false
mapBox = mapView.getMapboxMap().also {
logoPlugin?.enabled = false
mapView = binding.root.findViewById<MapView?>(R.id.mapView).also {
it.logo.enabled = false
it.compass.enabled = false
it.attribution.enabled = false
}
mapBox.setCamera(
CameraOptions.Builder()
.center(
Point.fromLngLat(
LATITUDE,
LONGITUDE
))
.zoom(ZOOM).build()
)
mapView.getMapboxMap().addOnMapLoadErrorListener(object :OnMapLoadErrorListener{
override fun onMapLoadError(eventData: MapLoadingErrorEventData) {
LogUtils.e("OnMapLoadErrorListener:${eventData.message}")
}
})
viewAnnotationManager = mapView.viewAnnotationManager
updateMapBox(mapView)
mapView.addRendererSetupErrorListener {
error -> LogUtils.e("RendererSetupErrorListener:${error}")
}
......@@ -94,9 +94,27 @@ class HomeFragment : Fragment() {
binding.defaultToggleMore.setOnClickListener {
moreFeaturesPopup.showPopupWindow(binding.defaultToggleMore)
}
viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED){
mapModel.obstaclesSource().collect{binding.defaultMapLayout.addObstaclesSource(it)}
mapModel.runnableAreaSource().collect{binding.defaultMapLayout.addRunnableAreaSource(it)}
mapModel.laneSource().collect{binding.defaultMapLayout.addLaneSource(it)}
mapModel.laneNodeSource().collect{binding.defaultMapLayout.addLaneNodeSource(it)}
mapModel.staticObjectsSource().collect{binding.defaultMapLayout.addStaticObjectsSource(it)}
mapModel.diggingWorkAreaSource().collect{binding.defaultMapLayout.addDiggingWorkAreaSource(it)}
mapModel.barricadeSource().collect{binding.defaultMapLayout.addBarricadeSource(it)}
mapModel.stationAreaSource().collect{binding.defaultMapLayout.addStationAreaSource(it)}
mapModel.parkSpotSource().collect{binding.defaultMapLayout.addParkSpotSource(it)}
mapModel.electronicFenceSource().collect{binding.defaultMapLayout.addElectronicFenceSource(it)}
mapModel.wetAreaSource().collect{binding.defaultMapLayout.addWetAreaSource(it)}
mapModel.dumpAreaSource().collect{binding.defaultMapLayout.addDumpAreaSource(it)}
}
}
return binding.root
}
private fun setTodayCarriedNum(num:Int){
val templateString = getString(R.string.today_carried_text, num)
val spannableString = SpannableString(templateString)
......@@ -114,10 +132,4 @@ class HomeFragment : Fragment() {
_binding = null
}
companion object {
private const val GEOJSON_SOURCE_ID = "tile"
private const val LATITUDE = 108.926593
private const val LONGITUDE = 34.213389
private const val ZOOM = 14.0
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package com.waytous.anticollision.ui.video
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.text.SpannableString
......@@ -9,50 +10,50 @@ import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.graphics.scale
import androidx.core.view.get
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
import com.blankj.utilcode.util.LogUtils
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem
import com.mapbox.geojson.FeatureCollection
import com.mapbox.geojson.Point
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.MapView
import com.mapbox.maps.MapboxMap
import com.mapbox.maps.Style
import com.mapbox.maps.ViewAnnotationOptions
import com.mapbox.maps.extension.style.expressions.dsl.generated.interpolate
import com.mapbox.maps.extension.style.expressions.dsl.generated.get
import com.mapbox.maps.extension.style.image.image
import com.mapbox.maps.extension.style.layers.generated.fillLayer
import com.mapbox.maps.extension.style.layers.generated.symbolLayer
import com.mapbox.maps.extension.style.layers.properties.generated.IconAnchor
import com.mapbox.maps.extension.style.layers.properties.generated.TextAnchor
import com.mapbox.maps.extension.style.layers.properties.generated.TextRotationAlignment
import com.mapbox.maps.extension.style.layers.properties.generated.Visibility
import com.mapbox.maps.extension.style.sources.generated.geoJsonSource
import com.mapbox.maps.extension.style.sources.generated.rasterDemSource
import com.mapbox.maps.extension.style.style
import com.mapbox.maps.extension.style.terrain.generated.terrain
import com.mapbox.maps.plugin.LocationPuck2D
import com.mapbox.maps.plugin.Plugin
import com.mapbox.maps.plugin.annotation.annotations
import com.mapbox.maps.plugin.annotation.generated.PointAnnotation
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationOptions
import com.mapbox.maps.plugin.annotation.generated.createPointAnnotationManager
import com.mapbox.maps.plugin.gestures.gestures
import com.mapbox.maps.plugin.locationcomponent.OnIndicatorBearingChangedListener
import com.mapbox.maps.plugin.locationcomponent.OnIndicatorPositionChangedListener
import com.mapbox.maps.plugin.attribution.attribution
import com.mapbox.maps.plugin.compass.compass
import com.mapbox.maps.plugin.locationcomponent.location
import com.mapbox.maps.plugin.logo.logo
import com.mapbox.maps.viewannotation.ViewAnnotationManager
import com.waytous.anticollision.R
import com.waytous.anticollision.api.ApiService
import com.waytous.anticollision.databinding.FragmentVideoHomeBinding
import com.waytous.anticollision.ui.MainViewModel
import com.waytous.anticollision.ui.view.MoreFeaturesPopup
import com.waytous.anticollision.ui.view.WorkStatusEditPopup
import com.waytous.anticollision.utils.getBitmapFromVectorDrawable
import com.waytous.anticollision.utils.setTextSize
import kotlinx.coroutines.launch
import java.io.File
class VideoHomeFragment : Fragment() {
......@@ -82,10 +83,16 @@ class VideoHomeFragment : Fragment() {
const val MY_VEHICLE_NORMAL = "my_vehicle_normal"
private const val GEOJSON_SOURCE_ID = "tile"
private const val LATITUDE = 108.926593
private const val LONGITUDE = 34.213389
private const val ZOOM = 14.0
private const val DUMP_AREA_SOURCE = "dumpareasource"
private const val DUMP_AREA_LAYER = "dumparealayer"
private const val DUMP_AREA_TEXT_LAYER = "dumpareatextlayer"
private const val RUNNABLE_AREA_SOURCE = "runableareasource"
private const val RUNNABLE_AREA_LAYER = "runablearealayer"
private const val LATITUDE = 119.7622539014
private const val LONGITUDE = 49.3795031825
// private const val LATITUDE = 108.926593
// private const val LONGITUDE = 34.213389
private const val ZOOM = 16.0
}
private val viewModel: VideoHomeViewModel by viewModels()
......@@ -119,6 +126,8 @@ class VideoHomeFragment : Fragment() {
binding.speedText.setTextSize(spannableString, templateString)
mapView = binding.root.findViewById<MapView?>(R.id.mapView).also {
it.logo.enabled = false
it.compass.enabled = false
it.attribution.enabled = false
}
mapboxMap = mapView.getMapboxMap()
viewAnnotationManager = mapView.viewAnnotationManager
......@@ -132,40 +141,64 @@ class VideoHomeFragment : Fragment() {
private fun initLocationComponent() {
val locationComponentPlugin = mapView.location
mapView.getMapboxMap().loadStyle(
style(styleUri = Style.MAPBOX_STREETS) {
+geoJsonSource(GEOJSON_SOURCE_ID) {
url("asset://xian.geojson")
lifecycleScope.launch {
val mapData = ApiService.create().dumpAreaVersion("-1")
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED){
mapView.getMapboxMap().loadStyle(
style(styleUri = MainViewModel.MY_MAP_BOX_STYLE) {
+geoJsonSource(DUMP_AREA_SOURCE) {
data(mapData?.geojson!!)
LogUtils.d(get("name").literalValue)
}
+fillLayer(DUMP_AREA_LAYER,DUMP_AREA_SOURCE){
fillColor("#886e26")
fillOpacity(0.85)
fillAntialias(false)
visibility(Visibility.VISIBLE)
}
+symbolLayer(DUMP_AREA_TEXT_LAYER, DUMP_AREA_SOURCE){
textColor(Color.BLACK)
textField(get("name"))
textFont(listOf("DIN Offc Pro Italic", "Arial Unicode MS Regular"))
textLineHeight(1.0)
textPadding(1.0)
textOffset(listOf(0.5,2.0))
textRotationAlignment(TextRotationAlignment.MAP)
textAnchor(TextAnchor.TOP)
textSize(16.0)
textMaxAngle(10.0)
visibility(Visibility.VISIBLE)
}
}
) {
val bitmap: Bitmap? =
activity?.getBitmapFromVectorDrawable(R.drawable.my_vehicle_normal, 4)
val annotationPlugin = mapView.annotations
val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
.withPoint(
Point.fromLngLat(
LONGITUDE,
LATITUDE
)
)
.withIconImage(bitmap!!.apply {
scale(bitmap.width / 4, bitmap.height / 4)
})
.withIconAnchor(IconAnchor.BOTTOM)
.withDraggable(false)
pointAnnotationManager = annotationPlugin.createPointAnnotationManager()
pointAnnotation = pointAnnotationManager.create(pointAnnotationOptions)
}
}
) {
val bitmap: Bitmap? =
activity?.getBitmapFromVectorDrawable(R.drawable.my_vehicle_normal, 4)
val annotationPlugin = mapView.annotations
val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
.withPoint(
Point.fromLngLat(
LATITUDE,
LONGITUDE
)
mapView.getMapboxMap().setCamera(
CameraOptions.Builder().center(
Point.fromLngLat(
LATITUDE,
LONGITUDE
)
).zoom(ZOOM).build()
)
.withIconImage(bitmap!!.apply {
scale(bitmap.width / 4, bitmap.height / 4)
})
.withIconAnchor(IconAnchor.BOTTOM)
.withDraggable(false)
pointAnnotationManager = annotationPlugin.createPointAnnotationManager()
pointAnnotation = pointAnnotationManager.create(pointAnnotationOptions)
}
}
mapView.getMapboxMap().setCamera(
CameraOptions.Builder().center(
Point.fromLngLat(
LATITUDE,
LONGITUDE
)
).zoom(ZOOM).build()
)
// locationComponentPlugin.locationPuck = LocationPuck2D(
// bearingImage = VectorDrawableCompat.create(
// resources,
......@@ -199,7 +232,7 @@ class VideoHomeFragment : Fragment() {
}
private fun initPlayer() {
val uri1 = Uri.fromFile(File(activity!!.filesDir, "飞书20230420-181456.mp4"))
val uri1 = Uri.fromFile(File(requireActivity().filesDir, "飞书20230420-181456.mp4"))
player1 = activity?.let {
ExoPlayer.Builder(it).build().apply {
setMediaItem(MediaItem.Builder().setUri(uri1).build())
......@@ -207,7 +240,7 @@ class VideoHomeFragment : Fragment() {
}
binding.videoView1.player = player1
player1?.prepare()
val uri2 = Uri.fromFile(File(activity!!.filesDir, "飞书20230420-181512.mp4"))
val uri2 = Uri.fromFile(File(requireActivity().filesDir, "飞书20230420-181512.mp4"))
player2 = activity?.let {
ExoPlayer.Builder(it).build().apply {
setMediaItem(MediaItem.Builder().setUri(uri2).build())
......
......@@ -15,6 +15,8 @@ import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
const val databaseName = "anti_collision.db"
/**
* 连接状态
* */
......
......@@ -2,7 +2,7 @@ package com.waytous.anticollision.utils
import android.content.Context
import android.content.SharedPreferences
import com.waytous.anticollision.MyApp
import com.waytous.anticollision.AntiCollisionApp
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
......@@ -10,7 +10,7 @@ class PreferenceDelegate<T>(private val name: String, private val default: T, pr
: ReadWriteProperty<Any?, T> {
private val prefs: SharedPreferences =
MyApp.instance().applicationContext.getSharedPreferences(prefName, Context.MODE_PRIVATE)
AntiCollisionApp.instance().applicationContext.getSharedPreferences(prefName, Context.MODE_PRIVATE)
@Synchronized
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
......
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="67dp"
android:height="6dp"
android:viewportWidth="67"
android:viewportHeight="6">
<path
android:pathData="M67,6l-67,0l0,-6l2,0l0,4l63,0l0,-4l2,0l0,6z"
android:fillColor="#dcdcdc"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="67dp"
android:height="6dp"
android:viewportWidth="67"
android:viewportHeight="6">
<path
android:pathData="M67,6l-67,0l0,-6l2,0l0,4l63,0l0,-4l2,0l0,6z"
android:fillColor="#2c2c2c"/>
</vector>
......@@ -15,10 +15,11 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
<CheckedTextView
android:id="@+id/itemFaultEngine"
style="@style/FaultCauseTextStyle"
android:text="@string/fault_cause_engine"
android:background="@drawable/background_fault_cause_item"
android:drawableTop="@drawable/background_fault_cause_item_engine"
android:layout_marginTop="77dp"
android:layout_marginStart="44dp"
......@@ -29,6 +30,7 @@
android:id="@+id/itemFaultMechanical"
style="@style/FaultCauseTextStyle"
android:text="@string/fault_cause_mechanical"
android:background="@drawable/background_fault_cause_item"
android:drawableTop="@drawable/background_fault_cause_item_mechanical"
android:layout_marginStart="32dp"
app:layout_constraintTop_toTopOf="@id/itemFaultEngine"
......@@ -39,6 +41,7 @@
android:id="@+id/itemFaultHydraulicSystem"
style="@style/FaultCauseTextStyle"
android:text="@string/fault_cause_hydraulic_system"
android:background="@drawable/background_fault_cause_item"
android:drawableTop="@drawable/background_fault_cause_item_hydraulic_system"
android:layout_marginStart="32dp"
app:layout_constraintTop_toTopOf="@id/itemFaultMechanical"
......@@ -51,6 +54,7 @@
style="@style/FaultCauseTextStyle"
android:layout_marginEnd="44dp"
android:layout_marginStart="32dp"
android:background="@drawable/background_fault_cause_item"
android:drawableTop="@drawable/background_fault_cause_item_electrical"
android:text="@string/fault_cause_electrical"
app:layout_constraintEnd_toEndOf="parent"
......@@ -61,6 +65,7 @@
android:id="@+id/itemFaultEdgeReduction"
style="@style/FaultCauseTextStyle"
android:layout_marginTop="28dp"
android:background="@drawable/background_fault_cause_item"
android:drawableTop="@drawable/background_fault_cause_item_edge_reduction"
android:text="@string/fault_cause_edge_reduction"
app:layout_constraintEnd_toEndOf="@+id/itemFaultEngine"
......@@ -70,6 +75,7 @@
android:id="@+id/itemFaultTire"
style="@style/FaultCauseTextStyle"
android:layout_marginStart="32dp"
android:background="@drawable/background_fault_cause_item"
android:drawableTop="@drawable/background_fault_cause_item_tire"
android:text="@string/fault_cause_tire"
app:layout_constraintTop_toTopOf="@id/itemFaultEdgeReduction"
......@@ -79,6 +85,7 @@
android:id="@+id/itemFaultEquipmentMaintenance"
style="@style/FaultCauseTextStyle"
android:layout_marginStart="32dp"
android:background="@drawable/background_fault_cause_item"
android:drawableTop="@drawable/background_fault_cause_item_equipment_maintenance"
android:text="@string/fault_cause_equipment_maintenance"
app:layout_constraintTop_toTopOf="@id/itemFaultTire"
......@@ -88,6 +95,7 @@
android:id="@+id/itemFaultOtherInputs"
style="@style/FaultCauseTextStyle"
android:layout_marginStart="32dp"
android:background="@drawable/background_fault_cause_item"
android:drawableTop="@drawable/background_fault_cause_item_other_inputs"
android:text="@string/fault_cause_other_inputs"
app:layout_constraintTop_toTopOf="@id/itemFaultEquipmentMaintenance"
......
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.BaseFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
\ No newline at end of file
......@@ -282,9 +282,8 @@
app:layout_constraintTop_toTopOf="@id/defaultToggleMore"
app:layout_constraintEnd_toEndOf="@id/defaultMapLayout" />
<include
<com.waytous.anticollision.ui.MapBoxLayout
android:id="@+id/defaultMapLayout"
layout="@layout/layout_map_box"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="16dp"
......
......@@ -7,102 +7,131 @@
android:background="@drawable/drawable_bg_map_box"
tools:context=".ui.MainActivity">
<com.mapbox.maps.MapView
android:id="@+id/mapView"
android:layout_width="0dp"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/collectDataText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:mapbox_resourcesAccessToken="@string/map_box_public_key"
app:mapbox_scaleBarBorderWidth="0dp"
app:mapbox_scaleBarGravity="bottom|end"
app:mapbox_scaleBarHeight="2dp"
app:mapbox_scaleBarIsMetricUnits="true"
app:mapbox_scaleBarMarginBottom="15dp"
app:mapbox_scaleBarMarginRight="12dp"
app:mapbox_scaleBarRatio="0.2"
app:mapbox_scaleBarTextBarMargin="10dp"
app:mapbox_scaleBarTextBorderWidth="5dp"
app:mapbox_scaleBarTextColor="@color/home_text_color"
app:mapbox_scaleBarTextSize="9sp"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/sos"
style="@style/MapBoxButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginTop="30dp"
android:contentDescription="@string/sos"
android:src="@drawable/background_sos_btn"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/emergency"
style="@style/MapBoxButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginBottom="25dp"
android:contentDescription="@string/emergency"
android:src="@mipmap/icon_driving_state_emergency"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/zoomLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="28dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.mapbox.maps.MapView
android:id="@+id/mapView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="@dimen/dp_3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:mapbox_resourcesAccessToken="@string/map_box_public_key"
app:mapbox_scaleBarBorderWidth="0dp"
app:mapbox_scaleBarGravity="bottom|end"
app:mapbox_scaleBarHeight="@dimen/dp_6"
app:mapbox_scaleBarIsMetricUnits="true"
app:mapbox_scaleBarMarginBottom="15dp"
app:mapbox_scaleBarMarginRight="24dp"
app:mapbox_scaleBarTextBarMargin="10dp"
app:mapbox_scaleBarTextBorderWidth="5dp"
app:mapbox_scaleBarTextColor="@color/home_text_color"
app:mapbox_scaleBarTextSize="@dimen/dp_18" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/zoomOut"
android:id="@+id/sos"
style="@style/MapBoxButtonStyle"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:contentDescription="@string/zoom_out"
android:src="@drawable/background_zoom_out" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:background="@color/color_ffcacaca"/>
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginTop="30dp"
android:contentDescription="@string/sos"
android:src="@drawable/background_sos_btn"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/zoomIn"
android:id="@+id/emergency"
style="@style/MapBoxButtonStyle"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:contentDescription="@string/zoom_in"
android:src="@drawable/background_zoom_in" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/locationTruck"
style="@style/MapBoxButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="28dp"
android:contentDescription="@string/location_truck"
android:src="@drawable/background_location_truck"
app:layout_constraintStart_toStartOf="@id/zoomLayout"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginBottom="25dp"
android:contentDescription="@string/emergency"
android:src="@mipmap/icon_driving_state_emergency"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/zoomLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="28dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/zoomOut"
style="@style/MapBoxButtonStyle"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:contentDescription="@string/zoom_out"
android:src="@drawable/background_zoom_out" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:background="@color/color_ffcacaca" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/zoomIn"
style="@style/MapBoxButtonStyle"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:contentDescription="@string/zoom_in"
android:src="@drawable/background_zoom_in" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/locationTruck"
style="@style/MapBoxButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/location_truck"
android:src="@drawable/background_location_truck"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/zoomLayout"
app:layout_constraintStart_toStartOf="@id/zoomLayout"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/toggleSafetyRange"
style="@style/MapBoxButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="34dp"
android:contentDescription="@string/toggle_safety_range"
android:src="@mipmap/icon_map_enable_safety_range_light"
app:layout_constraintEnd_toEndOf="@id/zoomLayout"
app:layout_constraintStart_toStartOf="@id/zoomLayout"
app:layout_constraintTop_toBottomOf="@id/locationTruck" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/collectDataText"
android:layout_width="0dp"
android:layout_height="@dimen/dp_56"
android:layout_marginStart="@dimen/dp_3"
android:layout_marginEnd="@dimen/dp_3"
android:gravity="center"
android:text="@string/collect_data_text"
android:visibility="gone"
android:textSize="@dimen/sp_20"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/toggleSafetyRange"
style="@style/MapBoxButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="34dp"
android:layout_marginEnd="28dp"
android:contentDescription="@string/toggle_safety_range"
android:src="@mipmap/icon_map_enable_safety_range_light"
app:layout_constraintStart_toStartOf="@id/zoomLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/locationTruck" />
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -3,7 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@id/navigation_video_Home">
app:startDestination="@id/navigation_home">
<fragment
android:id="@+id/navigation_home"
......
......@@ -9,6 +9,7 @@
<color name="white">#FFFFFFFF</color>
<color name="half_white">#80FFFFFF</color>
<color name="color_ff333333">#ff333333</color>
<color name="color_ff666666">#ff666666</color>
<color name="color_80333333">#80333333</color>
<color name="color_0052D8">#ff0052d8</color>
<color name="status_bg_color">#ebefefef</color>
......@@ -31,4 +32,5 @@
<color name="color_4d3c3c3c">#4d3c3c3c</color>
<color name="color_1a000000">#1a000000</color>
<color name="color_ff3684F9">#ff3684F9</color>
<color name="color_green">#00ff00</color>
</resources>
\ No newline at end of file
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="common_margin">@dimen/dp_15</dimen>
<dimen name="dp_m_60">-60dp</dimen>
<dimen name="dp_m_30">-30dp</dimen>
<dimen name="dp_m_20">-20dp</dimen>
<dimen name="dp_m_12">-12dp</dimen>
<dimen name="dp_m_10">-10dp</dimen>
<dimen name="dp_m_8">-8dp</dimen>
<dimen name="dp_m_5">-5dp</dimen>
<dimen name="dp_m_2">-2dp</dimen>
<dimen name="dp_m_1">-1dp</dimen>
<dimen name="dp_0">0dp</dimen>
<dimen name="dp_0_1">0.1dp</dimen>
<dimen name="dp_0_5">0.5dp</dimen>
<dimen name="dp_1">1dp</dimen>
<dimen name="dp_1_5">1.5dp</dimen>
<dimen name="dp_2">2dp</dimen>
<dimen name="dp_2_5">2.5dp</dimen>
<dimen name="dp_3">3dp</dimen>
<dimen name="dp_3_5">3.5dp</dimen>
<dimen name="dp_4">4dp</dimen>
<dimen name="dp_4_5">4.5dp</dimen>
<dimen name="dp_5">5dp</dimen>
<dimen name="dp_6">6dp</dimen>
<dimen name="dp_7">7dp</dimen>
<dimen name="dp_8">8dp</dimen>
<dimen name="dp_9">9dp</dimen>
<dimen name="dp_10">10dp</dimen>
<dimen name="dp_11">11dp</dimen>
<dimen name="dp_12">12dp</dimen>
<dimen name="dp_13">13dp</dimen>
<dimen name="dp_14">14dp</dimen>
<dimen name="dp_15">15dp</dimen>
<dimen name="dp_16">16dp</dimen>
<dimen name="dp_17">17dp</dimen>
<dimen name="dp_18">18dp</dimen>
<dimen name="dp_19">19dp</dimen>
<dimen name="dp_20">20dp</dimen>
<dimen name="dp_21">21dp</dimen>
<dimen name="dp_22">22dp</dimen>
<dimen name="dp_23">23dp</dimen>
<dimen name="dp_24">24dp</dimen>
<dimen name="dp_25">25dp</dimen>
<dimen name="dp_26">26dp</dimen>
<dimen name="dp_27">27dp</dimen>
<dimen name="dp_28">28dp</dimen>
<dimen name="dp_29">29dp</dimen>
<dimen name="dp_30">30dp</dimen>
<dimen name="dp_31">31dp</dimen>
<dimen name="dp_32">32dp</dimen>
<dimen name="dp_33">33dp</dimen>
<dimen name="dp_34">34dp</dimen>
<dimen name="dp_35">35dp</dimen>
<dimen name="dp_36">36dp</dimen>
<dimen name="dp_37">37dp</dimen>
<dimen name="dp_38">38dp</dimen>
<dimen name="dp_39">39dp</dimen>
<dimen name="dp_40">40dp</dimen>
<dimen name="dp_41">41dp</dimen>
<dimen name="dp_42">42dp</dimen>
<dimen name="dp_43">43dp</dimen>
<dimen name="dp_44">44dp</dimen>
<dimen name="dp_45">45dp</dimen>
<dimen name="dp_46">46dp</dimen>
<dimen name="dp_47">47dp</dimen>
<dimen name="dp_48">48dp</dimen>
<dimen name="dp_49">49dp</dimen>
<dimen name="dp_50">50dp</dimen>
<dimen name="dp_51">51dp</dimen>
<dimen name="dp_52">52dp</dimen>
<dimen name="dp_53">53dp</dimen>
<dimen name="dp_54">54dp</dimen>
<dimen name="dp_55">55dp</dimen>
<dimen name="dp_56">56dp</dimen>
<dimen name="dp_57">57dp</dimen>
<dimen name="dp_58">58dp</dimen>
<dimen name="dp_59">59dp</dimen>
<dimen name="dp_60">60dp</dimen>
<dimen name="dp_61">61dp</dimen>
<dimen name="dp_62">62dp</dimen>
<dimen name="dp_63">63dp</dimen>
<dimen name="dp_64">64dp</dimen>
<dimen name="dp_65">65dp</dimen>
<dimen name="dp_66">66dp</dimen>
<dimen name="dp_67">67dp</dimen>
<dimen name="dp_68">68dp</dimen>
<dimen name="dp_69">69dp</dimen>
<dimen name="dp_70">70dp</dimen>
<dimen name="dp_71">71dp</dimen>
<dimen name="dp_72">72dp</dimen>
<dimen name="dp_73">73dp</dimen>
<dimen name="dp_74">74dp</dimen>
<dimen name="dp_75">75dp</dimen>
<dimen name="dp_76">76dp</dimen>
<dimen name="dp_77">77dp</dimen>
<dimen name="dp_78">78dp</dimen>
<dimen name="dp_79">79dp</dimen>
<dimen name="dp_80">80dp</dimen>
<dimen name="dp_81">81dp</dimen>
<dimen name="dp_82">82dp</dimen>
<dimen name="dp_83">83dp</dimen>
<dimen name="dp_84">84dp</dimen>
<dimen name="dp_85">85dp</dimen>
<dimen name="dp_86">86dp</dimen>
<dimen name="dp_87">87dp</dimen>
<dimen name="dp_88">88dp</dimen>
<dimen name="dp_89">89dp</dimen>
<dimen name="dp_90">90dp</dimen>
<dimen name="dp_91">91dp</dimen>
<dimen name="dp_92">92dp</dimen>
<dimen name="dp_93">93dp</dimen>
<dimen name="dp_94">94dp</dimen>
<dimen name="dp_95">95dp</dimen>
<dimen name="dp_96">96dp</dimen>
<dimen name="dp_97">97dp</dimen>
<dimen name="dp_98">98dp</dimen>
<dimen name="dp_99">99dp</dimen>
<dimen name="dp_100">100dp</dimen>
<dimen name="dp_101">101dp</dimen>
<dimen name="dp_102">102dp</dimen>
<dimen name="dp_103">103dp</dimen>
<dimen name="dp_104">104dp</dimen>
<dimen name="dp_105">105dp</dimen>
<dimen name="dp_106">106dp</dimen>
<dimen name="dp_107">107dp</dimen>
<dimen name="dp_108">108dp</dimen>
<dimen name="dp_109">109dp</dimen>
<dimen name="dp_110">110dp</dimen>
<dimen name="dp_111">111dp</dimen>
<dimen name="dp_112">112dp</dimen>
<dimen name="dp_113">113dp</dimen>
<dimen name="dp_114">114dp</dimen>
<dimen name="dp_115">115dp</dimen>
<dimen name="dp_116">116dp</dimen>
<dimen name="dp_117">117dp</dimen>
<dimen name="dp_118">118dp</dimen>
<dimen name="dp_119">119dp</dimen>
<dimen name="dp_120">120dp</dimen>
<dimen name="dp_121">121dp</dimen>
<dimen name="dp_122">122dp</dimen>
<dimen name="dp_123">123dp</dimen>
<dimen name="dp_124">124dp</dimen>
<dimen name="dp_125">125dp</dimen>
<dimen name="dp_126">126dp</dimen>
<dimen name="dp_127">127dp</dimen>
<dimen name="dp_128">128dp</dimen>
<dimen name="dp_129">129dp</dimen>
<dimen name="dp_130">130dp</dimen>
<dimen name="dp_131">131dp</dimen>
<dimen name="dp_132">132dp</dimen>
<dimen name="dp_133">133dp</dimen>
<dimen name="dp_134">134dp</dimen>
<dimen name="dp_135">135dp</dimen>
<dimen name="dp_136">136dp</dimen>
<dimen name="dp_137">137dp</dimen>
<dimen name="dp_138">138dp</dimen>
<dimen name="dp_139">139dp</dimen>
<dimen name="dp_140">140dp</dimen>
<dimen name="dp_141">141dp</dimen>
<dimen name="dp_142">142dp</dimen>
<dimen name="dp_143">143dp</dimen>
<dimen name="dp_144">144dp</dimen>
<dimen name="dp_145">145dp</dimen>
<dimen name="dp_146">146dp</dimen>
<dimen name="dp_147">147dp</dimen>
<dimen name="dp_148">148dp</dimen>
<dimen name="dp_149">149dp</dimen>
<dimen name="dp_150">150dp</dimen>
<dimen name="dp_151">151dp</dimen>
<dimen name="dp_152">152dp</dimen>
<dimen name="dp_153">153dp</dimen>
<dimen name="dp_154">154dp</dimen>
<dimen name="dp_155">155dp</dimen>
<dimen name="dp_156">156dp</dimen>
<dimen name="dp_157">157dp</dimen>
<dimen name="dp_158">158dp</dimen>
<dimen name="dp_159">159dp</dimen>
<dimen name="dp_160">160dp</dimen>
<dimen name="dp_161">161dp</dimen>
<dimen name="dp_162">162dp</dimen>
<dimen name="dp_163">163dp</dimen>
<dimen name="dp_164">164dp</dimen>
<dimen name="dp_165">165dp</dimen>
<dimen name="dp_166">166dp</dimen>
<dimen name="dp_167">167dp</dimen>
<dimen name="dp_168">168dp</dimen>
<dimen name="dp_169">169dp</dimen>
<dimen name="dp_170">170dp</dimen>
<dimen name="dp_171">171dp</dimen>
<dimen name="dp_172">172dp</dimen>
<dimen name="dp_173">173dp</dimen>
<dimen name="dp_174">174dp</dimen>
<dimen name="dp_175">175dp</dimen>
<dimen name="dp_176">176dp</dimen>
<dimen name="dp_177">177dp</dimen>
<dimen name="dp_178">178dp</dimen>
<dimen name="dp_179">179dp</dimen>
<dimen name="dp_180">180dp</dimen>
<dimen name="dp_181">181dp</dimen>
<dimen name="dp_182">182dp</dimen>
<dimen name="dp_183">183dp</dimen>
<dimen name="dp_184">184dp</dimen>
<dimen name="dp_185">185dp</dimen>
<dimen name="dp_186">186dp</dimen>
<dimen name="dp_187">187dp</dimen>
<dimen name="dp_188">188dp</dimen>
<dimen name="dp_189">189dp</dimen>
<dimen name="dp_190">190dp</dimen>
<dimen name="dp_191">191dp</dimen>
<dimen name="dp_192">192dp</dimen>
<dimen name="dp_193">193dp</dimen>
<dimen name="dp_194">194dp</dimen>
<dimen name="dp_195">195dp</dimen>
<dimen name="dp_196">196dp</dimen>
<dimen name="dp_197">197dp</dimen>
<dimen name="dp_198">198dp</dimen>
<dimen name="dp_199">199dp</dimen>
<dimen name="dp_200">200dp</dimen>
<dimen name="dp_201">201dp</dimen>
<dimen name="dp_202">202dp</dimen>
<dimen name="dp_203">203dp</dimen>
<dimen name="dp_204">204dp</dimen>
<dimen name="dp_205">205dp</dimen>
<dimen name="dp_206">206dp</dimen>
<dimen name="dp_207">207dp</dimen>
<dimen name="dp_208">208dp</dimen>
<dimen name="dp_209">209dp</dimen>
<dimen name="dp_210">210dp</dimen>
<dimen name="dp_211">211dp</dimen>
<dimen name="dp_212">212dp</dimen>
<dimen name="dp_213">213dp</dimen>
<dimen name="dp_214">214dp</dimen>
<dimen name="dp_215">215dp</dimen>
<dimen name="dp_216">216dp</dimen>
<dimen name="dp_217">217dp</dimen>
<dimen name="dp_218">218dp</dimen>
<dimen name="dp_219">219dp</dimen>
<dimen name="dp_220">220dp</dimen>
<dimen name="dp_221">221dp</dimen>
<dimen name="dp_222">222dp</dimen>
<dimen name="dp_223">223dp</dimen>
<dimen name="dp_224">224dp</dimen>
<dimen name="dp_225">225dp</dimen>
<dimen name="dp_226">226dp</dimen>
<dimen name="dp_227">227dp</dimen>
<dimen name="dp_228">228dp</dimen>
<dimen name="dp_229">229dp</dimen>
<dimen name="dp_230">230dp</dimen>
<dimen name="dp_231">231dp</dimen>
<dimen name="dp_232">232dp</dimen>
<dimen name="dp_233">233dp</dimen>
<dimen name="dp_234">234dp</dimen>
<dimen name="dp_235">235dp</dimen>
<dimen name="dp_236">236dp</dimen>
<dimen name="dp_237">237dp</dimen>
<dimen name="dp_238">238dp</dimen>
<dimen name="dp_239">239dp</dimen>
<dimen name="dp_240">240dp</dimen>
<dimen name="dp_241">241dp</dimen>
<dimen name="dp_242">242dp</dimen>
<dimen name="dp_243">243dp</dimen>
<dimen name="dp_244">244dp</dimen>
<dimen name="dp_245">245dp</dimen>
<dimen name="dp_246">246dp</dimen>
<dimen name="dp_247">247dp</dimen>
<dimen name="dp_248">248dp</dimen>
<dimen name="dp_249">249dp</dimen>
<dimen name="dp_250">250dp</dimen>
<dimen name="dp_251">251dp</dimen>
<dimen name="dp_252">252dp</dimen>
<dimen name="dp_253">253dp</dimen>
<dimen name="dp_254">254dp</dimen>
<dimen name="dp_255">255dp</dimen>
<dimen name="dp_256">256dp</dimen>
<dimen name="dp_257">257dp</dimen>
<dimen name="dp_258">258dp</dimen>
<dimen name="dp_259">259dp</dimen>
<dimen name="dp_260">260dp</dimen>
<dimen name="dp_261">261dp</dimen>
<dimen name="dp_262">262dp</dimen>
<dimen name="dp_263">263dp</dimen>
<dimen name="dp_264">264dp</dimen>
<dimen name="dp_265">265dp</dimen>
<dimen name="dp_266">266dp</dimen>
<dimen name="dp_267">267dp</dimen>
<dimen name="dp_268">268dp</dimen>
<dimen name="dp_269">269dp</dimen>
<dimen name="dp_270">270dp</dimen>
<dimen name="dp_271">271dp</dimen>
<dimen name="dp_272">272dp</dimen>
<dimen name="dp_273">273dp</dimen>
<dimen name="dp_274">274dp</dimen>
<dimen name="dp_275">275dp</dimen>
<dimen name="dp_276">276dp</dimen>
<dimen name="dp_277">277dp</dimen>
<dimen name="dp_278">278dp</dimen>
<dimen name="dp_279">279dp</dimen>
<dimen name="dp_280">280dp</dimen>
<dimen name="dp_281">281dp</dimen>
<dimen name="dp_282">282dp</dimen>
<dimen name="dp_283">283dp</dimen>
<dimen name="dp_284">284dp</dimen>
<dimen name="dp_285">285dp</dimen>
<dimen name="dp_286">286dp</dimen>
<dimen name="dp_287">287dp</dimen>
<dimen name="dp_288">288dp</dimen>
<dimen name="dp_289">289dp</dimen>
<dimen name="dp_290">290dp</dimen>
<dimen name="dp_291">291dp</dimen>
<dimen name="dp_292">292dp</dimen>
<dimen name="dp_293">293dp</dimen>
<dimen name="dp_294">294dp</dimen>
<dimen name="dp_295">295dp</dimen>
<dimen name="dp_296">296dp</dimen>
<dimen name="dp_297">297dp</dimen>
<dimen name="dp_298">298dp</dimen>
<dimen name="dp_299">299dp</dimen>
<dimen name="dp_300">300dp</dimen>
<dimen name="dp_301">301dp</dimen>
<dimen name="dp_302">302dp</dimen>
<dimen name="dp_303">303dp</dimen>
<dimen name="dp_304">304dp</dimen>
<dimen name="dp_305">305dp</dimen>
<dimen name="dp_306">306dp</dimen>
<dimen name="dp_307">307dp</dimen>
<dimen name="dp_308">308dp</dimen>
<dimen name="dp_309">309dp</dimen>
<dimen name="dp_310">310dp</dimen>
<dimen name="dp_311">311dp</dimen>
<dimen name="dp_312">312dp</dimen>
<dimen name="dp_313">313dp</dimen>
<dimen name="dp_314">314dp</dimen>
<dimen name="dp_315">315dp</dimen>
<dimen name="dp_316">316dp</dimen>
<dimen name="dp_317">317dp</dimen>
<dimen name="dp_318">318dp</dimen>
<dimen name="dp_319">319dp</dimen>
<dimen name="dp_320">320dp</dimen>
<dimen name="dp_321">321dp</dimen>
<dimen name="dp_322">322dp</dimen>
<dimen name="dp_323">323dp</dimen>
<dimen name="dp_324">324dp</dimen>
<dimen name="dp_325">325dp</dimen>
<dimen name="dp_326">326dp</dimen>
<dimen name="dp_327">327dp</dimen>
<dimen name="dp_328">328dp</dimen>
<dimen name="dp_329">329dp</dimen>
<dimen name="dp_330">330dp</dimen>
<dimen name="dp_331">331dp</dimen>
<dimen name="dp_332">332dp</dimen>
<dimen name="dp_333">333dp</dimen>
<dimen name="dp_334">334dp</dimen>
<dimen name="dp_335">335dp</dimen>
<dimen name="dp_336">336dp</dimen>
<dimen name="dp_337">337dp</dimen>
<dimen name="dp_338">338dp</dimen>
<dimen name="dp_339">339dp</dimen>
<dimen name="dp_340">340dp</dimen>
<dimen name="dp_341">341dp</dimen>
<dimen name="dp_342">342dp</dimen>
<dimen name="dp_343">343dp</dimen>
<dimen name="dp_344">344dp</dimen>
<dimen name="dp_345">345dp</dimen>
<dimen name="dp_346">346dp</dimen>
<dimen name="dp_347">347dp</dimen>
<dimen name="dp_348">348dp</dimen>
<dimen name="dp_349">349dp</dimen>
<dimen name="dp_350">350dp</dimen>
<dimen name="dp_351">351dp</dimen>
<dimen name="dp_352">352dp</dimen>
<dimen name="dp_353">353dp</dimen>
<dimen name="dp_354">354dp</dimen>
<dimen name="dp_355">355dp</dimen>
<dimen name="dp_356">356dp</dimen>
<dimen name="dp_357">357dp</dimen>
<dimen name="dp_358">358dp</dimen>
<dimen name="dp_359">359dp</dimen>
<dimen name="dp_360">360dp</dimen>
<dimen name="dp_365">365dp</dimen>
<dimen name="dp_370">370dp</dimen>
<dimen name="dp_376">376dp</dimen>
<dimen name="dp_400">400dp</dimen>
<dimen name="dp_410">410dp</dimen>
<dimen name="dp_422">422dp</dimen>
<dimen name="dp_448">448dp</dimen>
<dimen name="dp_462">462dp</dimen>
<dimen name="dp_465">465dp</dimen>
<dimen name="dp_472">472dp</dimen>
<dimen name="dp_492">492dp</dimen>
<dimen name="dp_500">500dp</dimen>
<dimen name="dp_600">600dp</dimen>
<dimen name="dp_640">640dp</dimen>
<dimen name="dp_720">720dp</dimen>
<!-- font size,you can add if there is no one -->
<dimen name="sp_6">6sp</dimen>
<dimen name="sp_7">7sp</dimen>
<dimen name="sp_8">8sp</dimen>
<dimen name="sp_9">9sp</dimen>
<dimen name="sp_10">10sp</dimen>
<dimen name="sp_11">11sp</dimen>
<dimen name="sp_12">12sp</dimen>
<dimen name="sp_13">13sp</dimen>
<dimen name="sp_14">14sp</dimen>
<dimen name="sp_15">15sp</dimen>
<dimen name="sp_16">16sp</dimen>
<dimen name="sp_17">17sp</dimen>
<dimen name="sp_18">18sp</dimen>
<dimen name="sp_19">19sp</dimen>
<dimen name="sp_20">20sp</dimen>
<dimen name="sp_21">21sp</dimen>
<dimen name="sp_22">22sp</dimen>
<dimen name="sp_23">23sp</dimen>
<dimen name="sp_24">24sp</dimen>
<dimen name="sp_25">25sp</dimen>
<dimen name="sp_28">28sp</dimen>
<dimen name="sp_30">30sp</dimen>
<dimen name="sp_32">32sp</dimen>
<dimen name="sp_34">34sp</dimen>
<dimen name="sp_36">36sp</dimen>
<dimen name="sp_38">38sp</dimen>
<dimen name="sp_40">40sp</dimen>
<dimen name="sp_42">42sp</dimen>
<dimen name="sp_48">48sp</dimen>
</resources>
\ No newline at end of file
......@@ -68,6 +68,7 @@
<string name="fault_cause_equipment_maintenance">设备保养</string>
<string name="fault_cause_other_inputs">其他录入</string>
<string name="pls_input_cause">请输入原因说明</string>
<string name="collect_data_text">采集状态:%1s 采集点数:%2d 速度:%3dKM/h 当前位置:%4f,%5f 高程:%6fm</string>
<string name="confirm">确定</string>
<string name="cancel">取消</string>
......
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.3.1' apply false
id 'com.android.library' version '7.3.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
id 'com.android.application' version '7.4.2' apply false
id 'com.android.library' version '7.4.2' apply false
id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
id 'com.google.dagger.hilt.android' version '2.44' apply false
}
\ No newline at end of file
......@@ -15,6 +15,7 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
......
#Thu Feb 16 11:06:04 CST 2023
#Thu May 04 15:47:53 CST 2023
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment