增加质检结果展示页面
This commit is contained in:
parent
fa4ad254a5
commit
88326d3247
@ -4,6 +4,7 @@ plugins {
|
|||||||
id 'kotlin-kapt'
|
id 'kotlin-kapt'
|
||||||
id 'com.google.dagger.hilt.android'
|
id 'com.google.dagger.hilt.android'
|
||||||
id 'realm-android'
|
id 'realm-android'
|
||||||
|
id 'kotlin-parcelize' // 序列化
|
||||||
}
|
}
|
||||||
android {
|
android {
|
||||||
namespace 'com.navinfo.omqs'
|
namespace 'com.navinfo.omqs'
|
||||||
@ -11,7 +12,7 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.navinfo.omqs"
|
applicationId "com.navinfo.omqs"
|
||||||
minSdk 24
|
minSdk 26
|
||||||
targetSdk 33
|
targetSdk 33
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
@ -36,14 +37,17 @@ android {
|
|||||||
viewBinding true
|
viewBinding true
|
||||||
dataBinding true
|
dataBinding true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation project(':collect-library')
|
implementation project(':collect-library')
|
||||||
implementation 'androidx.core:core-ktx:1.7.0'
|
implementation 'androidx.core:core-ktx:1.9.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
implementation 'com.google.android.material:material:1.8.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
|
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
|
||||||
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
|
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
|
||||||
@ -55,17 +59,26 @@ dependencies {
|
|||||||
// 文件管理 https://github.com/K1rakishou/Fuck-Storage-Access-Framework
|
// 文件管理 https://github.com/K1rakishou/Fuck-Storage-Access-Framework
|
||||||
implementation 'com.github.K1rakishou:Fuck-Storage-Access-Framework:v1.1.3'
|
implementation 'com.github.K1rakishou:Fuck-Storage-Access-Framework:v1.1.3'
|
||||||
// Android工具类库 https://blankj.com/2016/07/31/android-utils-code/
|
// Android工具类库 https://blankj.com/2016/07/31/android-utils-code/
|
||||||
implementation 'com.blankj:utilcodex:1.30.1'
|
implementation 'com.blankj:utilcodex:1.31.1'
|
||||||
//依赖注入
|
//依赖注入
|
||||||
//hilt
|
//hilt
|
||||||
implementation "com.google.dagger:hilt-android:2.44"
|
implementation 'com.google.dagger:hilt-android:2.45'
|
||||||
kapt "com.google.dagger:hilt-compiler:2.44"
|
kapt 'com.google.dagger:hilt-compiler:2.45'
|
||||||
|
|
||||||
// Retrofit 网络请求相关
|
// Retrofit 网络请求相关
|
||||||
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||||
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
||||||
implementation("com.squareup.okhttp3:okhttp:4.9.0")
|
implementation('com.squareup.okhttp3:okhttp:5.0.0-alpha.11')
|
||||||
implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
|
implementation('com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.11')
|
||||||
|
|
||||||
|
kapt 'android.arch.persistence.room:compiler:1.1.1'// compiler 需要用 room 的
|
||||||
|
kapt "androidx.room:room-compiler:2.5.1"
|
||||||
|
kapt "androidx.room:room-ktx:2.5.1"
|
||||||
|
|
||||||
|
//读取excel word等文件
|
||||||
|
implementation 'org.apache.poi:poi:5.2.3'
|
||||||
|
implementation 'org.apache.poi:poi-ooxml:5.2.3'
|
||||||
|
|
||||||
}
|
}
|
||||||
//允许引用生成的代码
|
//允许引用生成的代码
|
||||||
kapt {
|
kapt {
|
||||||
|
@ -5,6 +5,7 @@ import android.util.Log
|
|||||||
import com.navinfo.omqs.tools.FileManager
|
import com.navinfo.omqs.tools.FileManager
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
|
import io.realm.RealmConfiguration
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -12,7 +13,17 @@ import java.io.File
|
|||||||
@HiltAndroidApp
|
@HiltAndroidApp
|
||||||
class OMQSApplication : Application() {
|
class OMQSApplication : Application() {
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
FileManager.initRootDir(this)
|
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
FileManager.initRootDir(this)
|
||||||
|
Realm.init(this)
|
||||||
|
val password = "password".encodeToByteArray().copyInto(ByteArray(64))
|
||||||
|
// 1110000011000010111001101110011011101110110111101110010011001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
// Log.d("", "密码是: ${BigInteger(1, password).toString(2).padStart(64, '0')}")
|
||||||
|
val config = RealmConfiguration.Builder()
|
||||||
|
.directory(File(Constant.DATA_PATH))
|
||||||
|
.name("HDData")
|
||||||
|
// .encryptionKey(password)
|
||||||
|
.build()
|
||||||
|
Realm.setDefaultConfiguration(config)
|
||||||
}
|
}
|
||||||
}
|
}
|
6
app/src/main/java/com/navinfo/omqs/bean/BaseBean.kt
Normal file
6
app/src/main/java/com/navinfo/omqs/bean/BaseBean.kt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package com.navinfo.omqs.bean
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
open class BaseBean : Serializable, Cloneable {
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.navinfo.omqs.bean
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
|
||||||
|
@Entity(tableName = "OfflineMapCity")
|
||||||
|
@Parcelize
|
||||||
|
data class OfflineMapCityBean @JvmOverloads constructor(
|
||||||
|
@PrimaryKey
|
||||||
|
var id: String = "",
|
||||||
|
var fileName: String = "",
|
||||||
|
var name: String = "",
|
||||||
|
var url: String = "",
|
||||||
|
var version: Long = 0L,
|
||||||
|
var fileSize: Long = 0L,
|
||||||
|
var currentSize: Long = 0L,
|
||||||
|
var status: Int = NONE
|
||||||
|
) : Parcelable {
|
||||||
|
|
||||||
|
companion object Status {
|
||||||
|
const val NONE = 0 //无状态
|
||||||
|
const val WAITING = 1 //等待中
|
||||||
|
const val LOADING = 2 //下载中
|
||||||
|
const val PAUSE = 3 //暂停
|
||||||
|
const val ERROR = 4 //错误
|
||||||
|
const val DONE = 5 //完成
|
||||||
|
const val UPDATE = 6 //有新版本要更新
|
||||||
|
}
|
||||||
|
|
||||||
|
// // status的转换对象
|
||||||
|
// var statusEnum: StatusEnum
|
||||||
|
// get() {
|
||||||
|
// return try {
|
||||||
|
// StatusEnum.values().find { it.status == status }!!
|
||||||
|
// } catch (e: IllegalArgumentException) {
|
||||||
|
// StatusEnum.NONE
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// set(value) {
|
||||||
|
// status = value.status
|
||||||
|
// }
|
||||||
|
|
||||||
|
fun getFileSizeText(): String {
|
||||||
|
return if (fileSize < 1024.0)
|
||||||
|
"$fileSize B"
|
||||||
|
else if (fileSize < 1048576.0)
|
||||||
|
"%.2f K".format(fileSize / 1024.0)
|
||||||
|
else if (fileSize < 1073741824.0)
|
||||||
|
"%.2f M".format(fileSize / 1048576.0)
|
||||||
|
else
|
||||||
|
"%.2f M".format(fileSize / 1073741824.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
115
app/src/main/java/com/navinfo/omqs/bean/QsRecord.kt
Normal file
115
app/src/main/java/com/navinfo/omqs/bean/QsRecord.kt
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package com.navinfo.omqs.bean
|
||||||
|
|
||||||
|
import io.realm.RealmObject
|
||||||
|
import io.realm.annotations.PrimaryKey
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhjch
|
||||||
|
* @version V1.0
|
||||||
|
* @ClassName: Rd_qcRecord
|
||||||
|
* @Date 2016/1/12
|
||||||
|
* @Description: ${TODO}(质检对象)
|
||||||
|
*/
|
||||||
|
open class QsRecord @JvmOverloads constructor(
|
||||||
|
/**
|
||||||
|
* id 主键
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@PrimaryKey var id: String = "",
|
||||||
|
/**
|
||||||
|
* linkPid 绑定的道路ID
|
||||||
|
*/
|
||||||
|
var linkPid: String = "",
|
||||||
|
/**
|
||||||
|
*问题分类
|
||||||
|
*/
|
||||||
|
var classType: String = "",
|
||||||
|
/**
|
||||||
|
* 问题类型
|
||||||
|
*/
|
||||||
|
var type: String = "",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 问题现象
|
||||||
|
*/
|
||||||
|
var phenomenon: String = "",
|
||||||
|
/**
|
||||||
|
* 问题描述
|
||||||
|
*/
|
||||||
|
var description: String = "",
|
||||||
|
/**
|
||||||
|
* 设置initial_cause
|
||||||
|
* @param initial_cause
|
||||||
|
* initial_cause
|
||||||
|
*/
|
||||||
|
// var initial_cause: String? = StringEntity.STRING_DEFAULT
|
||||||
|
// /**
|
||||||
|
// * 获取root_cause
|
||||||
|
// * @return root_cause
|
||||||
|
// */
|
||||||
|
// /**
|
||||||
|
// * 设置root_cause
|
||||||
|
// * @param root_cause
|
||||||
|
// * root_cause
|
||||||
|
// */
|
||||||
|
////根本原因(RCA)
|
||||||
|
// var root_cause: String? = StringEntity.STRING_DEFAULT
|
||||||
|
// /**
|
||||||
|
// * 获取check_userid
|
||||||
|
// * @return check_userid
|
||||||
|
// */
|
||||||
|
// /**
|
||||||
|
// * 设置check_userid
|
||||||
|
// * @param check_userid
|
||||||
|
// * check_userid
|
||||||
|
// */
|
||||||
|
////质检员
|
||||||
|
// var check_userid: String? = StringEntity.STRING_DEFAULT
|
||||||
|
// /**
|
||||||
|
// * 获取check_time
|
||||||
|
// * @return check_time
|
||||||
|
// */
|
||||||
|
// /**
|
||||||
|
// * 设置check_time
|
||||||
|
// * @param check_time
|
||||||
|
// * check_time
|
||||||
|
// */
|
||||||
|
////质检日期
|
||||||
|
// var check_time: String? = StringEntity.STRING_DEFAULT
|
||||||
|
// /**
|
||||||
|
// * 获取confirm_userid
|
||||||
|
// * @return confirm_userid
|
||||||
|
// */
|
||||||
|
// /**
|
||||||
|
// * 设置confirm_userid
|
||||||
|
// * @param confirm_userid
|
||||||
|
// * confirm_userid
|
||||||
|
// */
|
||||||
|
////确认人
|
||||||
|
// var confirm_userid: String? = StringEntity.STRING_DEFAULT
|
||||||
|
// /**
|
||||||
|
// * 获取t_lifecycle
|
||||||
|
// * @return t_lifecycle
|
||||||
|
// */
|
||||||
|
// /**
|
||||||
|
// * 设置t_lifecycle
|
||||||
|
// * @param t_lifecycle
|
||||||
|
// * t_lifecycle
|
||||||
|
// */
|
||||||
|
////状态 0 无; 1 删除;2 更新;3 新增;
|
||||||
|
// var t_lifecycle = 0
|
||||||
|
// /**
|
||||||
|
// * 获取t_status
|
||||||
|
// * @return t_status
|
||||||
|
// */
|
||||||
|
// /**
|
||||||
|
// * 设置t_status
|
||||||
|
// * @param t_status
|
||||||
|
// * t_status
|
||||||
|
// */
|
||||||
|
////问题记录提交状态 0 未提交;1 已提交;
|
||||||
|
// var t_status = 0
|
||||||
|
) : RealmObject(
|
||||||
|
|
||||||
|
)
|
30
app/src/main/java/com/navinfo/omqs/bean/ScProblemTypeBean.kt
Normal file
30
app/src/main/java/com/navinfo/omqs/bean/ScProblemTypeBean.kt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package com.navinfo.omqs.bean
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Entity(tableName = "ScProblemType")
|
||||||
|
@Parcelize
|
||||||
|
data class ScProblemTypeBean(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0,
|
||||||
|
/**
|
||||||
|
* 问题分类
|
||||||
|
*/
|
||||||
|
@ColumnInfo("CLASS_TYPE")
|
||||||
|
var classType: String = "",
|
||||||
|
/**
|
||||||
|
* 问题类型
|
||||||
|
*/
|
||||||
|
@ColumnInfo("TYPE")
|
||||||
|
var problemType: String = "",
|
||||||
|
/**
|
||||||
|
* 问题现象
|
||||||
|
*/
|
||||||
|
@ColumnInfo("PHENOMENON")
|
||||||
|
var phenomenon: String = ""
|
||||||
|
|
||||||
|
) : Parcelable
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.navinfo.omqs.bean
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Entity(tableName = "ScRootCauseAnalysis")
|
||||||
|
@Parcelize
|
||||||
|
data class ScRootCauseAnalysisBean(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0,
|
||||||
|
/**
|
||||||
|
* 问题环节
|
||||||
|
*/
|
||||||
|
@ColumnInfo("PROBLEM_LINK")
|
||||||
|
var problemLink: String = "",
|
||||||
|
/**
|
||||||
|
* 问题原因
|
||||||
|
*/
|
||||||
|
@ColumnInfo("PROBLEM_CAUSE")
|
||||||
|
var problemCause: String = "",
|
||||||
|
) : Parcelable
|
21
app/src/main/java/com/navinfo/omqs/db/RoomAppDatabase.kt
Normal file
21
app/src/main/java/com/navinfo/omqs/db/RoomAppDatabase.kt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package com.navinfo.omqs.db
|
||||||
|
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||||
|
import com.navinfo.omqs.bean.ScProblemTypeBean
|
||||||
|
import com.navinfo.omqs.bean.ScRootCauseAnalysisBean
|
||||||
|
import com.navinfo.omqs.db.dao.OfflineMapDao
|
||||||
|
import com.navinfo.omqs.db.dao.ScProblemTypeDao
|
||||||
|
import com.navinfo.omqs.db.dao.ScRootCauseAnalysisDao
|
||||||
|
|
||||||
|
@Database(
|
||||||
|
entities = [OfflineMapCityBean::class, ScProblemTypeBean::class, ScRootCauseAnalysisBean::class],
|
||||||
|
version = 1,
|
||||||
|
exportSchema = false
|
||||||
|
)
|
||||||
|
abstract class RoomAppDatabase : RoomDatabase() {
|
||||||
|
abstract fun getOfflineMapDao(): OfflineMapDao
|
||||||
|
abstract fun getScProblemTypeDao(): ScProblemTypeDao
|
||||||
|
abstract fun getScRootCauseAnalysisDao(): ScRootCauseAnalysisDao
|
||||||
|
}
|
23
app/src/main/java/com/navinfo/omqs/db/dao/OfflineMapDao.kt
Normal file
23
app/src/main/java/com/navinfo/omqs/db/dao/OfflineMapDao.kt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.navinfo.omqs.db.dao
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface OfflineMapDao {
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
suspend fun insert(message: OfflineMapCityBean): Long
|
||||||
|
|
||||||
|
@Update(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun update(message: OfflineMapCityBean)
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insertOrUpdate(list: List<OfflineMapCityBean>)
|
||||||
|
|
||||||
|
@Query("select * from OfflineMapCity order by id")
|
||||||
|
suspend fun getOfflineMapList(): List<OfflineMapCityBean>
|
||||||
|
|
||||||
|
@Query("select * from OfflineMapCity where status != 0 order by id")
|
||||||
|
suspend fun getOfflineMapListWithOutNone(): List<OfflineMapCityBean>
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.navinfo.omqs.db.dao
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase.getDatabase
|
||||||
|
import com.navinfo.omqs.bean.ScProblemTypeBean
|
||||||
|
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface ScProblemTypeDao {
|
||||||
|
// @Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
// suspend fun insert(bean: ScProblemTypeBean): Long
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insertList(list: List<ScProblemTypeBean>)
|
||||||
|
|
||||||
|
|
||||||
|
@Query("delete from ScProblemType")
|
||||||
|
suspend fun deleteAll()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新整个数据库表,由于没有
|
||||||
|
*/
|
||||||
|
@Transaction
|
||||||
|
suspend fun insertOrUpdateList(list: List<ScProblemTypeBean>) {
|
||||||
|
//先删除
|
||||||
|
deleteAll()
|
||||||
|
//后插入
|
||||||
|
insertList(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取问题分类,并去重
|
||||||
|
*/
|
||||||
|
@Query("select DISTINCT CLASS_TYPE from ScProblemType order by CLASS_TYPE")
|
||||||
|
suspend fun findClassTypeList(): List<String>?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取问题类型,并去重
|
||||||
|
*/
|
||||||
|
@Query("select DISTINCT TYPE from ScProblemType where CLASS_TYPE=:type order by TYPE")
|
||||||
|
suspend fun findProblemTypeList(type: String): List<String>
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Query("select PHENOMENON from ScProblemType where CLASS_TYPE=:classType and TYPE=:type order by PHENOMENON")
|
||||||
|
suspend fun getPhenomenonList(classType: String, type: String): List<String>
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.navinfo.omqs.db.dao
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import com.navinfo.omqs.bean.ScRootCauseAnalysisBean
|
||||||
|
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface ScRootCauseAnalysisDao {
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insertList(list: List<ScRootCauseAnalysisBean>)
|
||||||
|
|
||||||
|
|
||||||
|
@Query("delete from ScRootCauseAnalysis")
|
||||||
|
suspend fun deleteAll()
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
suspend fun insertOrUpdateList(list: List<ScRootCauseAnalysisBean>) {
|
||||||
|
//先删除
|
||||||
|
deleteAll()
|
||||||
|
//后插入
|
||||||
|
insertList(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,12 +1,16 @@
|
|||||||
package com.navinfo.omqs.hilt
|
package com.navinfo.omqs.hilt
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.room.Room
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.navinfo.omqs.Constant
|
import com.navinfo.omqs.Constant
|
||||||
import com.navinfo.omqs.OMQSApplication
|
import com.navinfo.omqs.OMQSApplication
|
||||||
|
import com.navinfo.omqs.db.RoomAppDatabase
|
||||||
import com.navinfo.omqs.http.RetrofitNetworkServiceAPI
|
import com.navinfo.omqs.http.RetrofitNetworkServiceAPI
|
||||||
import com.navinfo.omqs.tools.RealmCoroutineScope
|
import com.tencent.wcdb.database.SQLiteCipherSpec
|
||||||
|
import com.tencent.wcdb.room.db.WCDBOpenHelperFactory
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
@ -95,12 +99,41 @@ class GlobalModule {
|
|||||||
return retrofit.create(RetrofitNetworkServiceAPI::class.java)
|
return retrofit.create(RetrofitNetworkServiceAPI::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* realm 注册
|
|
||||||
*/
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideRealmService(context: Application): RealmCoroutineScope {
|
@Provides
|
||||||
return RealmCoroutineScope(context)
|
fun provideDatabase(context: Application): RoomAppDatabase {
|
||||||
|
val DB_PASSWORD = "123456";
|
||||||
|
val cipherSpec = SQLiteCipherSpec()
|
||||||
|
.setPageSize(1024)
|
||||||
|
.setSQLCipherVersion(3)
|
||||||
|
val factory = WCDBOpenHelperFactory()
|
||||||
|
// .passphrase(DB_PASSWORD.toByteArray()) // passphrase to the database, remove this line for plain-text
|
||||||
|
.cipherSpec(cipherSpec) // cipher to use, remove for default settings
|
||||||
|
.writeAheadLoggingEnabled(true) // enable WAL mode, remove if not needed
|
||||||
|
.asyncCheckpointEnabled(true); // enable asynchronous checkpoint, remove if not needed
|
||||||
|
|
||||||
|
return Room.databaseBuilder(
|
||||||
|
context,
|
||||||
|
RoomAppDatabase::class.java,
|
||||||
|
"${Constant.DATA_PATH}/omqs.db"
|
||||||
|
)
|
||||||
|
|
||||||
|
// [WCDB] Specify open helper to use WCDB database implementation instead
|
||||||
|
// of the Android framework.
|
||||||
|
.openHelperFactory(factory)
|
||||||
|
|
||||||
|
// Wipes and rebuilds instead of migrating if no Migration object.
|
||||||
|
// Migration is not part of this codelab.
|
||||||
|
// .fallbackToDestructiveMigration().addCallback(sRoomDatabaseCallback)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * realm 注册
|
||||||
|
// */
|
||||||
|
// @Provides
|
||||||
|
// @Singleton
|
||||||
|
// fun provideRealmService(context: Application): RealmCoroutineScope {
|
||||||
|
// return RealmCoroutineScope(context)
|
||||||
|
// }
|
||||||
}
|
}
|
@ -1,9 +1,9 @@
|
|||||||
package com.navinfo.omqs.hilt
|
package com.navinfo.omqs.hilt
|
||||||
|
|
||||||
import com.navinfo.collect.library.map.NIMapController
|
import com.navinfo.collect.library.map.NIMapController
|
||||||
|
import com.navinfo.omqs.db.RoomAppDatabase
|
||||||
import com.navinfo.omqs.http.RetrofitNetworkServiceAPI
|
import com.navinfo.omqs.http.RetrofitNetworkServiceAPI
|
||||||
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
|
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
|
||||||
import com.navinfo.omqs.tools.RealmCoroutineScope
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
@ -28,9 +28,10 @@ class MainActivityModule {
|
|||||||
@Provides
|
@Provides
|
||||||
fun providesOfflineMapDownloadManager(
|
fun providesOfflineMapDownloadManager(
|
||||||
networkServiceAPI: RetrofitNetworkServiceAPI,
|
networkServiceAPI: RetrofitNetworkServiceAPI,
|
||||||
realmManager: RealmCoroutineScope
|
roomAppDatabase: RoomAppDatabase,
|
||||||
|
mapController: NIMapController
|
||||||
): OfflineMapDownloadManager =
|
): OfflineMapDownloadManager =
|
||||||
OfflineMapDownloadManager(networkServiceAPI, realmManager)
|
OfflineMapDownloadManager(networkServiceAPI, roomAppDatabase, mapController)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实验失败,这样创建,viewmodel不会在activity销毁的时候同时销毁
|
* 实验失败,这样创建,viewmodel不会在activity销毁的时候同时销毁
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.navinfo.omqs.http
|
package com.navinfo.omqs.http
|
||||||
|
|
||||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.navinfo.omqs.http
|
package com.navinfo.omqs.http
|
||||||
|
|
||||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.navinfo.omqs.http
|
package com.navinfo.omqs.http
|
||||||
|
|
||||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
|
@ -2,16 +2,19 @@ package com.navinfo.omqs.http.offlinemapdownload
|
|||||||
|
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
import com.navinfo.collect.library.map.NIMapController
|
||||||
|
import com.navinfo.omqs.db.RoomAppDatabase
|
||||||
|
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||||
import com.navinfo.omqs.http.RetrofitNetworkServiceAPI
|
import com.navinfo.omqs.http.RetrofitNetworkServiceAPI
|
||||||
import com.navinfo.omqs.tools.RealmCoroutineScope
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 管理离线地图下载
|
* 管理离线地图下载
|
||||||
*/
|
*/
|
||||||
class OfflineMapDownloadManager(
|
class OfflineMapDownloadManager(
|
||||||
val netApi: RetrofitNetworkServiceAPI, val realmManager: RealmCoroutineScope
|
val netApi: RetrofitNetworkServiceAPI,
|
||||||
|
val roomDatabase: RoomAppDatabase,
|
||||||
|
val mapController: NIMapController
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* 最多同时下载数量
|
* 最多同时下载数量
|
||||||
|
@ -4,8 +4,8 @@ import android.util.Log
|
|||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
|
||||||
import com.navinfo.omqs.Constant
|
import com.navinfo.omqs.Constant
|
||||||
|
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -32,8 +32,8 @@ class OfflineMapDownloadScope(
|
|||||||
/**
|
/**
|
||||||
* 管理观察者,同时只有一个就行了
|
* 管理观察者,同时只有一个就行了
|
||||||
*/
|
*/
|
||||||
// private var observer: Observer<OfflineMapCityBean>? = null
|
private val observer = Observer<Any> {}
|
||||||
private var lifecycleOwner: LifecycleOwner? = null
|
// private var lifecycleOwner: LifecycleOwner? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*通知UI更新
|
*通知UI更新
|
||||||
@ -89,10 +89,10 @@ class OfflineMapDownloadScope(
|
|||||||
if (cityBean.status != status || status == OfflineMapCityBean.LOADING) {
|
if (cityBean.status != status || status == OfflineMapCityBean.LOADING) {
|
||||||
cityBean.status = status
|
cityBean.status = status
|
||||||
downloadData.postValue(cityBean)
|
downloadData.postValue(cityBean)
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
downloadManager.realmManager.launch {
|
downloadManager.roomDatabase.getOfflineMapDao().update(cityBean)
|
||||||
downloadManager.realmManager.insertOrUpdate(cityBean)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ class OfflineMapDownloadScope(
|
|||||||
*/
|
*/
|
||||||
fun observer(owner: LifecycleOwner, ob: Observer<OfflineMapCityBean>) {
|
fun observer(owner: LifecycleOwner, ob: Observer<OfflineMapCityBean>) {
|
||||||
removeObserver()
|
removeObserver()
|
||||||
this.lifecycleOwner = owner
|
// this.lifecycleOwner = owner
|
||||||
downloadData.observe(owner, ob)
|
downloadData.observe(owner, ob)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +156,9 @@ class OfflineMapDownloadScope(
|
|||||||
fileTemp.renameTo(File("${Constant.OFFLINE_MAP_PATH}${cityBean.fileName}"))
|
fileTemp.renameTo(File("${Constant.OFFLINE_MAP_PATH}${cityBean.fileName}"))
|
||||||
Log.e("jingo", "文件下载完成 修改文件 $res")
|
Log.e("jingo", "文件下载完成 修改文件 $res")
|
||||||
change(OfflineMapCityBean.DONE)
|
change(OfflineMapCityBean.DONE)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
downloadManager.mapController.layerManagerHandler.loadBaseMap()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
change(OfflineMapCityBean.PAUSE)
|
change(OfflineMapCityBean.PAUSE)
|
||||||
}
|
}
|
||||||
@ -168,9 +171,10 @@ class OfflineMapDownloadScope(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun removeObserver() {
|
fun removeObserver() {
|
||||||
lifecycleOwner?.let {
|
downloadData.observeForever(observer)
|
||||||
downloadData.removeObservers(it)
|
// lifecycleOwner?.let {
|
||||||
null
|
downloadData.removeObserver(observer)
|
||||||
}
|
// null
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,8 @@
|
|||||||
package com.navinfo.omqs.tools
|
package com.navinfo.omqs.tools
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
|
||||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
|
||||||
import com.navinfo.omqs.Constant
|
import com.navinfo.omqs.Constant
|
||||||
|
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class FileManager {
|
class FileManager {
|
||||||
|
@ -1,57 +1,47 @@
|
|||||||
package com.navinfo.omqs.tools
|
//package com.navinfo.omqs.tools
|
||||||
|
//
|
||||||
import android.app.Application
|
//import android.app.Application
|
||||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
//import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
||||||
import com.navinfo.omqs.Constant
|
//import com.navinfo.omqs.Constant
|
||||||
import io.realm.Realm
|
//import io.realm.Realm
|
||||||
import io.realm.RealmConfiguration
|
//import io.realm.RealmConfiguration
|
||||||
import io.realm.RealmModel
|
//import io.realm.RealmModel
|
||||||
import io.realm.Sort
|
//import io.realm.Sort
|
||||||
import io.realm.kotlin.where
|
//import io.realm.kotlin.where
|
||||||
import kotlinx.coroutines.CoroutineScope
|
//import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
//import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.newSingleThreadContext
|
//import kotlinx.coroutines.newSingleThreadContext
|
||||||
import java.io.File
|
//import java.io.File
|
||||||
|
//
|
||||||
class RealmCoroutineScope(context: Application) :
|
//class RealmCoroutineScope(context: Application) :
|
||||||
CoroutineScope by CoroutineScope(newSingleThreadContext("RealmThread")) {
|
// CoroutineScope by CoroutineScope(newSingleThreadContext("RealmThread")) {
|
||||||
lateinit var realm: Realm
|
// lateinit var realm: Realm
|
||||||
|
//
|
||||||
init {
|
// init {
|
||||||
launch {
|
// launch {
|
||||||
Realm.init(context)
|
// realm = Realm.getDefaultInstance()
|
||||||
val password = "password".encodeToByteArray().copyInto(ByteArray(64))
|
// }
|
||||||
// 1110000011000010111001101110011011101110110111101110010011001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
// }
|
||||||
// Log.d("", "密码是: ${BigInteger(1, password).toString(2).padStart(64, '0')}")
|
//
|
||||||
val config = RealmConfiguration.Builder()
|
// suspend fun getOfflineCityList(): List<OfflineMapCityBean> {
|
||||||
.directory(File(Constant.DATA_PATH))
|
// var list: List<OfflineMapCityBean> = mutableListOf()
|
||||||
.name("HDData")
|
// realm.executeTransaction {
|
||||||
// .encryptionKey(password)
|
// val objects = realm.where<OfflineMapCityBean>().findAll().sort("id", Sort.ASCENDING)
|
||||||
.build()
|
// list = realm.copyFromRealm(objects)
|
||||||
Realm.setDefaultConfiguration(config)
|
// }
|
||||||
realm = Realm.getDefaultInstance()
|
// return list
|
||||||
}
|
// }
|
||||||
}
|
//
|
||||||
|
// suspend fun insertOrUpdate(objects: Collection<RealmModel?>?) {
|
||||||
suspend fun getOfflineCityList(): List<OfflineMapCityBean> {
|
// realm.executeTransaction {
|
||||||
var list: List<OfflineMapCityBean> = mutableListOf()
|
// realm.insertOrUpdate(objects)
|
||||||
realm.executeTransaction {
|
// }
|
||||||
val objects = realm.where<OfflineMapCityBean>().findAll().sort("id", Sort.ASCENDING)
|
// }
|
||||||
list = realm.copyFromRealm(objects)
|
//
|
||||||
}
|
// suspend fun insertOrUpdate(realmModel: RealmModel?) {
|
||||||
return list
|
// realm.executeTransaction {
|
||||||
}
|
// realm.insertOrUpdate(realmModel)
|
||||||
|
// }
|
||||||
suspend fun insertOrUpdate(objects: Collection<RealmModel?>?) {
|
// }
|
||||||
realm.executeTransaction {
|
//
|
||||||
realm.insertOrUpdate(objects)
|
//}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun insertOrUpdate(realmModel: RealmModel?) {
|
|
||||||
realm.executeTransaction {
|
|
||||||
realm.insertOrUpdate(realmModel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
package com.navinfo.omqs.ui
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.core.view.WindowCompat
|
|
||||||
import androidx.navigation.ui.AppBarConfiguration
|
|
||||||
import com.github.k1rakishou.fsaf.FileChooser
|
|
||||||
import com.github.k1rakishou.fsaf.callback.FSAFActivityCallbacks
|
|
||||||
import com.navinfo.omqs.databinding.ActivityMainBinding
|
|
||||||
import com.navinfo.omqs.ui.activity.PermissionsActivity
|
|
||||||
|
|
||||||
class MainActivity : PermissionsActivity(), FSAFActivityCallbacks {
|
|
||||||
|
|
||||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
|
||||||
private lateinit var binding: ActivityMainBinding
|
|
||||||
private val fileChooser by lazy { FileChooser(this@MainActivity) }
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
|
||||||
setContentView(binding.root)
|
|
||||||
|
|
||||||
// val navController = findNavController(R.id.nav_host_fragment_content_main)
|
|
||||||
// appBarConfiguration = AppBarConfiguration(navController.graph)
|
|
||||||
// setupActionBarWithNavController(navController, appBarConfiguration)
|
|
||||||
|
|
||||||
fileChooser.setCallbacks(this@MainActivity)
|
|
||||||
// binding.fab.setOnClickListener { view ->
|
|
||||||
// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
|
||||||
// .setAnchorView(R.id.fab)
|
|
||||||
// .setAction("Action", null).show()
|
|
||||||
// // 开始数据导入功能
|
|
||||||
// fileChooser.openChooseFileDialog(object: FileChooserCallback() {
|
|
||||||
// override fun onCancel(reason: String) {
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onResult(uri: Uri) {
|
|
||||||
// val file = UriUtils.uri2File(uri)
|
|
||||||
// Snackbar.make(view, "文件大小为:${file.length()}", Snackbar.LENGTH_LONG)
|
|
||||||
// .show()
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPermissionsGranted() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPermissionsDenied() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
||||||
// // Inflate the menu; this adds items to the action bar if it is present.
|
|
||||||
// menuInflater.inflate(R.menu.menu_main, menu)
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
|
|
||||||
// override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
// // Handle action bar item clicks here. The action bar will
|
|
||||||
// // automatically handle clicks on the Home/Up button, so long
|
|
||||||
// // as you specify a parent activity in AndroidManifest.xml.
|
|
||||||
// return when (item.itemId) {
|
|
||||||
// R.id.action_settings -> true
|
|
||||||
// else -> super.onOptionsItemSelected(item)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onSupportNavigateUp(): Boolean {
|
|
||||||
// val navController = findNavController(R.id.nav_host_fragment_content_main)
|
|
||||||
// return navController.navigateUp(appBarConfiguration)
|
|
||||||
// || super.onSupportNavigateUp()
|
|
||||||
// }
|
|
||||||
|
|
||||||
override fun fsafStartActivityForResult(intent: Intent, requestCode: Int) {
|
|
||||||
startActivityForResult(intent, requestCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
|
||||||
fileChooser.onActivityResult(requestCode, resultCode, data)
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,10 +8,10 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.navinfo.omqs.bean.LoginUserBean
|
import com.navinfo.omqs.bean.LoginUserBean
|
||||||
|
import com.navinfo.omqs.db.RoomAppDatabase
|
||||||
import com.navinfo.omqs.http.NetResult
|
import com.navinfo.omqs.http.NetResult
|
||||||
import com.navinfo.omqs.http.NetworkService
|
import com.navinfo.omqs.http.NetworkService
|
||||||
import com.navinfo.omqs.tools.FileManager
|
import com.navinfo.omqs.tools.FileManager
|
||||||
import com.navinfo.omqs.tools.RealmCoroutineScope
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import okio.IOException
|
import okio.IOException
|
||||||
@ -57,7 +57,7 @@ enum class LoginStatus {
|
|||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class LoginViewModel @Inject constructor(
|
class LoginViewModel @Inject constructor(
|
||||||
private val networkService: NetworkService,
|
private val networkService: NetworkService,
|
||||||
private val realmManager: RealmCoroutineScope
|
private val roomAppDatabase: RoomAppDatabase
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
//用户信息
|
//用户信息
|
||||||
val loginUser: MutableLiveData<LoginUserBean> = MutableLiveData()
|
val loginUser: MutableLiveData<LoginUserBean> = MutableLiveData()
|
||||||
@ -126,9 +126,7 @@ class LoginViewModel @Inject constructor(
|
|||||||
for (cityBean in result.data) {
|
for (cityBean in result.data) {
|
||||||
FileManager.checkOfflineMapFileInfo(cityBean)
|
FileManager.checkOfflineMapFileInfo(cityBean)
|
||||||
}
|
}
|
||||||
realmManager.launch {
|
roomAppDatabase.getOfflineMapDao().insertOrUpdate(result.data)
|
||||||
realmManager.insertOrUpdate(result.data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is NetResult.Error -> {
|
is NetResult.Error -> {
|
||||||
|
@ -7,6 +7,7 @@ import androidx.activity.viewModels
|
|||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.navigation.findNavController
|
||||||
import com.navinfo.collect.library.map.NIMapController
|
import com.navinfo.collect.library.map.NIMapController
|
||||||
import com.navinfo.omqs.Constant
|
import com.navinfo.omqs.Constant
|
||||||
import com.navinfo.omqs.R
|
import com.navinfo.omqs.R
|
||||||
@ -28,6 +29,7 @@ class MainActivity : BaseActivity() {
|
|||||||
//注入地图控制器
|
//注入地图控制器
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var mapController: NIMapController
|
lateinit var mapController: NIMapController
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var offlineMapDownloadManager: OfflineMapDownloadManager
|
lateinit var offlineMapDownloadManager: OfflineMapDownloadManager
|
||||||
|
|
||||||
@ -39,9 +41,9 @@ class MainActivity : BaseActivity() {
|
|||||||
//初始化地图
|
//初始化地图
|
||||||
mapController.init(
|
mapController.init(
|
||||||
this,
|
this,
|
||||||
binding.mapView.mainActivityMap,
|
binding.mainActivityMap,
|
||||||
null,
|
null,
|
||||||
Constant.ROOT_PATH + "/map/"
|
Constant.MAP_PATH
|
||||||
)
|
)
|
||||||
//关联生命周期
|
//关联生命周期
|
||||||
binding.lifecycleOwner = this
|
binding.lifecycleOwner = this
|
||||||
@ -83,4 +85,11 @@ class MainActivity : BaseActivity() {
|
|||||||
binding.mainActivityDrawer.open()
|
binding.mainActivityDrawer.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击录音按钮
|
||||||
|
*/
|
||||||
|
fun voiceOnclick() {
|
||||||
|
val naviController = findNavController(R.id.main_activity_right_fragment)
|
||||||
|
naviController.navigate(R.id.EvaluationResultFragment)
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.navinfo.omqs.ui.fragment.empty
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.navinfo.omqs.databinding.FragmentEmptyBinding
|
||||||
|
|
||||||
|
class EmptyFragment :Fragment(){
|
||||||
|
private var _binding: FragmentEmptyBinding? = null
|
||||||
|
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
// private val viewModel by lazy { viewModels<EvaluationResultViewModel>().value}
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
_binding = FragmentEmptyBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
|
||||||
|
class EvaluationResultAdapter(activity: FragmentActivity, val fragmentList: List<Fragment>) :
|
||||||
|
FragmentStateAdapter(activity) {
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return fragmentList.size
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createFragment(position: Int): Fragment {
|
||||||
|
return fragmentList[position]
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,131 @@
|
|||||||
|
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
import com.navinfo.omqs.R
|
||||||
|
import com.navinfo.omqs.databinding.FragmentEvaluationResultBinding
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class EvaluationResultFragment : Fragment() {
|
||||||
|
private var _binding: FragmentEvaluationResultBinding? = null
|
||||||
|
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
private val viewModel by lazy { viewModels<EvaluationResultViewModel>().value }
|
||||||
|
private var phenomenonFragmentAdapter: EvaluationResultAdapter? = null
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
_binding = FragmentEvaluationResultBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
//返回按钮
|
||||||
|
binding.evaluationBar.setNavigationOnClickListener {
|
||||||
|
findNavController().popBackStack()
|
||||||
|
}
|
||||||
|
//监听数据变化
|
||||||
|
viewModel.classTypeListLiveData.observe(viewLifecycleOwner) {
|
||||||
|
if (it == null || it.isEmpty()) {
|
||||||
|
Toast.makeText(requireContext(), "还没有导入元数据!", Toast.LENGTH_SHORT).show()
|
||||||
|
} else {
|
||||||
|
binding.evaluationClassType.adapter =
|
||||||
|
ArrayAdapter(requireContext(), R.layout.text_item_select, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//选择问题分类的回调
|
||||||
|
binding.evaluationClassType.onItemSelectedListener =
|
||||||
|
object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(
|
||||||
|
parent: AdapterView<*>?, view: View?, position: Int, id: Long
|
||||||
|
) {
|
||||||
|
viewModel.getProblemTypeList(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 监听联动选择的内容
|
||||||
|
*/
|
||||||
|
viewModel.problemTypeListLiveData.observe(viewLifecycleOwner) {
|
||||||
|
binding.evaluationClassTabLayout.let { tabLayout ->
|
||||||
|
tabLayout.removeAllTabs()
|
||||||
|
val fragmentList = mutableListOf<Fragment>()
|
||||||
|
for (item in it) {
|
||||||
|
val tab = tabLayout.newTab()
|
||||||
|
tab.text = item
|
||||||
|
tabLayout.addTab(tab)
|
||||||
|
fragmentList.add(PhenomenonFragment(viewModel.currentClassType,item))
|
||||||
|
}
|
||||||
|
phenomenonFragmentAdapter =
|
||||||
|
activity?.let { a -> EvaluationResultAdapter(a, fragmentList) }
|
||||||
|
binding.evaluationViewpager.adapter = phenomenonFragmentAdapter
|
||||||
|
|
||||||
|
TabLayoutMediator(
|
||||||
|
binding.evaluationClassTabLayout,
|
||||||
|
binding.evaluationViewpager
|
||||||
|
) { tab, position ->
|
||||||
|
tab.text = it[position]
|
||||||
|
}.attach()
|
||||||
|
updateHeight(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//获取数据
|
||||||
|
viewModel.getClassTypeList()
|
||||||
|
binding.evaluationViewpager.registerOnPageChangeCallback(object :
|
||||||
|
ViewPager2.OnPageChangeCallback() {
|
||||||
|
override fun onPageSelected(position: Int) {
|
||||||
|
super.onPageSelected(position)
|
||||||
|
updateHeight(position)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun updateHeight(position: Int) {
|
||||||
|
phenomenonFragmentAdapter?.let {
|
||||||
|
if (it.fragmentList.size > position) {
|
||||||
|
val fragment: Fragment = it.fragmentList[position]
|
||||||
|
if (fragment.view != null) {
|
||||||
|
val viewWidth = View.MeasureSpec.makeMeasureSpec(
|
||||||
|
fragment.requireView().width, View.MeasureSpec.EXACTLY
|
||||||
|
)
|
||||||
|
val viewHeight =
|
||||||
|
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
||||||
|
fragment.requireView().measure(viewWidth, viewHeight)
|
||||||
|
binding.evaluationViewpager.let { viewpager ->
|
||||||
|
if (viewpager.layoutParams.height != fragment.requireView().measuredHeight) {
|
||||||
|
//必须要用对象去接收,然后修改该对象再采用该对象,否则无法生效...
|
||||||
|
val layoutParams: ViewGroup.LayoutParams =
|
||||||
|
viewpager.layoutParams
|
||||||
|
layoutParams.height = fragment.requireView().measuredHeight
|
||||||
|
viewpager.layoutParams = layoutParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.navinfo.omqs.db.RoomAppDatabase
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import okhttp3.Dispatcher
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class EvaluationResultViewModel @Inject constructor(
|
||||||
|
private val roomAppDatabase: RoomAppDatabase,
|
||||||
|
) : ViewModel() {
|
||||||
|
init {
|
||||||
|
Log.e("jingo", "EvaluationResultViewModel 创建了 ${hashCode()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
super.onCleared()
|
||||||
|
Log.e("jingo", "EvaluationResultViewModel 销毁了 ${hashCode()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 问题分类 liveData
|
||||||
|
*/
|
||||||
|
|
||||||
|
val classTypeListLiveData = MutableLiveData<List<String>?>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 问题类型 liveData
|
||||||
|
*/
|
||||||
|
|
||||||
|
val problemTypeListLiveData = MutableLiveData<List<String>>()
|
||||||
|
|
||||||
|
var currentClassType: String = ""
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询数据库,获取问题分类
|
||||||
|
*/
|
||||||
|
fun getClassTypeList() {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val list = roomAppDatabase.getScProblemTypeDao().findClassTypeList()
|
||||||
|
classTypeListLiveData.postValue(list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询问题类型
|
||||||
|
*/
|
||||||
|
fun getProblemTypeList(index: Int) {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
classTypeListLiveData.value?.let {
|
||||||
|
if (index < it.size) {
|
||||||
|
currentClassType = it[index]
|
||||||
|
val list =
|
||||||
|
roomAppDatabase.getScProblemTypeDao().findProblemTypeList(currentClassType)
|
||||||
|
problemTypeListLiveData.postValue(list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPhenomenonList() {
|
||||||
|
viewModelScope.launch (Dispatchers.IO){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.navinfo.omqs.R
|
||||||
|
import com.navinfo.omqs.databinding.TextItemSelectBinding
|
||||||
|
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
|
||||||
|
import com.navinfo.omqs.ui.other.BaseViewHolder
|
||||||
|
|
||||||
|
class PhenomenonAdapter() : BaseRecyclerViewAdapter<String>() {
|
||||||
|
override fun getItemViewRes(position: Int): Int {
|
||||||
|
return R.layout.text_item_select
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
|
||||||
|
val viewBinding =
|
||||||
|
TextItemSelectBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
|
return BaseViewHolder(viewBinding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
|
||||||
|
(holder.viewBinding as TextItemSelectBinding).itemId.text = data[position]
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.navinfo.omqs.ui.fragment.evaluationresult
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.navinfo.omqs.databinding.FragmentPhenomenonBinding
|
||||||
|
import com.navinfo.omqs.db.RoomAppDatabase
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class PhenomenonFragment(private val classType: String, private val title: String) :
|
||||||
|
Fragment() {
|
||||||
|
@Inject
|
||||||
|
lateinit var roomAppDatabase: RoomAppDatabase
|
||||||
|
private var _binding: FragmentPhenomenonBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
_binding = FragmentPhenomenonBinding.inflate(inflater, container, false)
|
||||||
|
Log.e("jingo", "PhenomenonFragment onCreateView ${hashCode()}")
|
||||||
|
return binding.root
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
binding.phenomenonRecyclerview.setHasFixedSize(true)
|
||||||
|
binding.phenomenonRecyclerview.layoutManager = LinearLayoutManager(context)
|
||||||
|
val adapter = PhenomenonAdapter()
|
||||||
|
binding.phenomenonRecyclerview.adapter = adapter
|
||||||
|
lifecycleScope.launch {
|
||||||
|
Log.e("jingo", "$classType $title ")
|
||||||
|
val list = roomAppDatabase.getScProblemTypeDao().getPhenomenonList(classType, title)
|
||||||
|
Log.e("jingo", "${list.toString()}")
|
||||||
|
adapter.refreshData(list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
Log.e("jingo", "PhenomenonFragment onDestroyView ${hashCode()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,6 @@ package com.navinfo.omqs.ui.fragment.offlinemap
|
|||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import dagger.hilt.EntryPoint
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 离线地图主页面,viewpage适配器
|
* 离线地图主页面,viewpage适配器
|
||||||
|
@ -6,9 +6,9 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
|
||||||
import com.navinfo.omqs.R
|
import com.navinfo.omqs.R
|
||||||
import com.navinfo.omqs.databinding.AdapterOfflineMapCityBinding
|
import com.navinfo.omqs.databinding.AdapterOfflineMapCityBinding
|
||||||
|
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||||
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
|
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
|
||||||
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
|
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
|
||||||
import com.navinfo.omqs.ui.other.BaseViewHolder
|
import com.navinfo.omqs.ui.other.BaseViewHolder
|
||||||
@ -22,7 +22,7 @@ import javax.inject.Inject
|
|||||||
*使用 LiveData 的 observeForever 然后在 ViewHolder 销毁前手动调用 removeObserver
|
*使用 LiveData 的 observeForever 然后在 ViewHolder 销毁前手动调用 removeObserver
|
||||||
*使用 LifecycleRegistry 给 ViewHolder 分发生命周期(这里使用了这个)
|
*使用 LifecycleRegistry 给 ViewHolder 分发生命周期(这里使用了这个)
|
||||||
*/
|
*/
|
||||||
class OfflineMapCityListAdapter @Inject constructor(
|
class OfflineMapCityListAdapter(
|
||||||
private val downloadManager: OfflineMapDownloadManager, private val context: Context
|
private val downloadManager: OfflineMapDownloadManager, private val context: Context
|
||||||
) : BaseRecyclerViewAdapter<OfflineMapCityBean>() {
|
) : BaseRecyclerViewAdapter<OfflineMapCityBean>() {
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ class OfflineMapCityListAdapter @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int {
|
override fun getItemViewRes(position: Int): Int {
|
||||||
return R.layout.adapter_offline_map_city
|
return R.layout.adapter_offline_map_city
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,10 @@ import android.content.Context
|
|||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.navinfo.collect.library.data.entity.OfflineMapCityBean
|
import com.navinfo.omqs.db.RoomAppDatabase
|
||||||
import com.navinfo.omqs.tools.FileManager
|
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||||
import com.navinfo.omqs.tools.RealmCoroutineScope
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import io.realm.Realm
|
|
||||||
import io.realm.Sort
|
|
||||||
import io.realm.kotlin.where
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -22,6 +18,7 @@ import javax.inject.Inject
|
|||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class OfflineMapCityListViewModel @Inject constructor(
|
class OfflineMapCityListViewModel @Inject constructor(
|
||||||
@ApplicationContext val context: Context,
|
@ApplicationContext val context: Context,
|
||||||
|
private val roomDatabase: RoomAppDatabase
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val cityListLiveData = MutableLiveData<List<OfflineMapCityBean>>()
|
val cityListLiveData = MutableLiveData<List<OfflineMapCityBean>>()
|
||||||
@ -31,13 +28,14 @@ class OfflineMapCityListViewModel @Inject constructor(
|
|||||||
*/
|
*/
|
||||||
fun getCityList() {
|
fun getCityList() {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val realm = Realm.getDefaultInstance()
|
// val realm = Realm.getDefaultInstance()
|
||||||
val objects = realm.where<OfflineMapCityBean>().findAll().sort("id", Sort.ASCENDING)
|
// val objects = realm.where<OfflineMapCityBean>().findAll().sort("id", Sort.ASCENDING)
|
||||||
val list = realm.copyFromRealm(objects)
|
// val list = realm.copyFromRealm(objects)
|
||||||
realm.close()
|
// realm.close()
|
||||||
for (item in list) {
|
// for (item in list) {
|
||||||
FileManager.checkOfflineMapFileInfo(item)
|
// FileManager.checkOfflineMapFileInfo(item)
|
||||||
}
|
// }
|
||||||
|
val list = roomDatabase.getOfflineMapDao().getOfflineMapList()
|
||||||
cityListLiveData.postValue(list)
|
cityListLiveData.postValue(list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,16 @@
|
|||||||
package com.navinfo.omqs.ui.fragment.offlinemap
|
package com.navinfo.omqs.ui.fragment.offlinemap
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.google.android.material.tabs.TabLayout
|
|
||||||
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import com.navinfo.omqs.databinding.FragmentOfflineMapBinding
|
import com.navinfo.omqs.databinding.FragmentOfflineMapBinding
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 离线地图
|
* 离线地图总页面
|
||||||
*/
|
*/
|
||||||
class OfflineMapFragment : Fragment() {
|
class OfflineMapFragment : Fragment() {
|
||||||
|
|
||||||
|
@ -6,16 +6,33 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.google.android.material.tabs.TabLayout
|
import androidx.fragment.app.viewModels
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
import com.navinfo.omqs.databinding.FragmentOfflineMapBinding
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.navinfo.omqs.databinding.FragmentOfflineMapStateListBinding
|
import com.navinfo.omqs.databinding.FragmentOfflineMapStateListBinding
|
||||||
|
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 离线地图管理页面
|
||||||
|
*/
|
||||||
|
@AndroidEntryPoint
|
||||||
class OfflineMapStateListFragment : Fragment() {
|
class OfflineMapStateListFragment : Fragment() {
|
||||||
|
@Inject
|
||||||
|
lateinit var downloadManager: OfflineMapDownloadManager
|
||||||
private var _binding: FragmentOfflineMapStateListBinding? = null
|
private var _binding: FragmentOfflineMapStateListBinding? = null
|
||||||
|
private val viewModel by viewModels<OfflineMapStateListViewModel>()
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
private val adapter: OfflineMapCityListAdapter by lazy {
|
||||||
|
OfflineMapCityListAdapter(
|
||||||
|
downloadManager,
|
||||||
|
requireContext()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
@ -27,11 +44,24 @@ class OfflineMapStateListFragment : Fragment() {
|
|||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
val layoutManager = LinearLayoutManager(context)
|
||||||
|
//// 设置 RecyclerView 的固定大小,避免在滚动时重新计算视图大小和布局,提高性能
|
||||||
|
binding.offlineMapCityStateListRecyclerview.setHasFixedSize(true)
|
||||||
|
binding.offlineMapCityStateListRecyclerview.layoutManager = layoutManager
|
||||||
|
binding.offlineMapCityStateListRecyclerview.adapter = adapter
|
||||||
|
viewModel.cityListLiveData.observe(viewLifecycleOwner) {
|
||||||
|
adapter.refreshData(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
viewModel.getCityList()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.navinfo.omqs.ui.fragment.offlinemap
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.navinfo.omqs.db.RoomAppDatabase
|
||||||
|
import com.navinfo.omqs.bean.OfflineMapCityBean
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 离线地图城市列表viewModel
|
||||||
|
*/
|
||||||
|
@HiltViewModel
|
||||||
|
class OfflineMapStateListViewModel @Inject constructor(
|
||||||
|
@ApplicationContext val context: Context,
|
||||||
|
private val roomDatabase: RoomAppDatabase
|
||||||
|
) : ViewModel() {
|
||||||
|
|
||||||
|
val cityListLiveData = MutableLiveData<List<OfflineMapCityBean>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 去获取正在下载或 已经下载的离线地图列表
|
||||||
|
*/
|
||||||
|
fun getCityList() {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val list = roomDatabase.getOfflineMapDao().getOfflineMapListWithOutNone()
|
||||||
|
if (cityListLiveData.value != null) {
|
||||||
|
if (cityListLiveData.value!!.size != list.size)
|
||||||
|
cityListLiveData.postValue(list)
|
||||||
|
}else{
|
||||||
|
cityListLiveData.postValue(list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +0,0 @@
|
|||||||
package com.navinfo.omqs.ui.fragment.offlinemap
|
|
||||||
|
|
||||||
import com.navinfo.omqs.databinding.AdapterOfflineMapCityBinding
|
|
||||||
import com.navinfo.omqs.ui.other.BaseViewHolder
|
|
||||||
|
|
||||||
class OfflineMapViewHolder(dataBinding: AdapterOfflineMapCityBinding) : BaseViewHolder(dataBinding) {
|
|
||||||
init{
|
|
||||||
dataBinding.offlineMapDownloadBtn
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,10 +15,12 @@ import com.github.k1rakishou.fsaf.callback.FSAFActivityCallbacks
|
|||||||
import com.github.k1rakishou.fsaf.callback.FileChooserCallback
|
import com.github.k1rakishou.fsaf.callback.FileChooserCallback
|
||||||
import com.navinfo.omqs.R
|
import com.navinfo.omqs.R
|
||||||
import com.navinfo.omqs.databinding.FragmentPersonalCenterBinding
|
import com.navinfo.omqs.databinding.FragmentPersonalCenterBinding
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 个人中心
|
* 个人中心
|
||||||
*/
|
*/
|
||||||
|
@AndroidEntryPoint
|
||||||
class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks {
|
class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks {
|
||||||
|
|
||||||
private var _binding: FragmentPersonalCenterBinding? = null
|
private var _binding: FragmentPersonalCenterBinding? = null
|
||||||
@ -54,6 +56,18 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
R.id.personal_center_menu_import_yuan_data->{
|
||||||
|
// 用户选中导入数据,打开文件选择器,用户选择导入的数据文件目录
|
||||||
|
fileChooser.openChooseFileDialog(object: FileChooserCallback() {
|
||||||
|
override fun onCancel(reason: String) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResult(uri: Uri) {
|
||||||
|
viewModel.importScProblemData(uri)
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,89 @@
|
|||||||
package com.navinfo.omqs.ui.fragment.personalcenter
|
package com.navinfo.omqs.ui.fragment.personalcenter
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import android.util.Log
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.blankj.utilcode.util.UriUtils
|
||||||
|
import com.navinfo.omqs.bean.ScProblemTypeBean
|
||||||
|
import com.navinfo.omqs.bean.ScRootCauseAnalysisBean
|
||||||
|
import com.navinfo.omqs.db.RoomAppDatabase
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.apache.poi.ss.usermodel.Cell
|
||||||
|
import org.apache.poi.ss.usermodel.Row
|
||||||
|
import org.apache.poi.ss.usermodel.Sheet
|
||||||
|
import org.apache.poi.ss.usermodel.WorkbookFactory
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class PersonalCenterViewModel: ViewModel() {
|
@HiltViewModel
|
||||||
|
class PersonalCenterViewModel @Inject constructor(
|
||||||
|
private val roomAppDatabase: RoomAppDatabase
|
||||||
|
) : ViewModel() {
|
||||||
fun importOmdbData(omdbFile: File) {
|
fun importOmdbData(omdbFile: File) {
|
||||||
// 检查File是否为sqlite数据库
|
// 检查File是否为sqlite数据库
|
||||||
if (omdbFile == null || omdbFile.exists()) {
|
if (omdbFile == null || !omdbFile.exists()) {
|
||||||
throw Exception("文件不存在")
|
throw Exception("文件不存在")
|
||||||
}
|
}
|
||||||
if (!omdbFile.name.endsWith(".sqlite") and !omdbFile.name.endsWith("db")) {
|
if (!omdbFile.name.endsWith(".sqlite") and !omdbFile.name.endsWith("db")) {
|
||||||
throw Exception("文件不存在")
|
throw Exception("文件不存在")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun importScProblemData(uri: Uri) {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val file = UriUtils.uri2File(uri)
|
||||||
|
val inputStream: InputStream =
|
||||||
|
FileInputStream(file) //getAssets().open("sample.xlsx")
|
||||||
|
val workbook = WorkbookFactory.create(inputStream)
|
||||||
|
//获取所有sheet
|
||||||
|
val sheet1 = workbook.getSheet("SC_PROBLEM_TYPE")
|
||||||
|
sheet1?.let {
|
||||||
|
val rowCount: Int = it.physicalNumberOfRows // 获取行数
|
||||||
|
val list = mutableListOf<ScProblemTypeBean>()
|
||||||
|
for (i in 1 until rowCount) {
|
||||||
|
val row: Row = it.getRow(i) // 获取行
|
||||||
|
val cellCount: Int = row.physicalNumberOfCells // 获取列数
|
||||||
|
if (cellCount == 3) {
|
||||||
|
val bean = ScProblemTypeBean()
|
||||||
|
bean.classType = row.getCell(0).stringCellValue
|
||||||
|
bean.problemType = row.getCell(1).stringCellValue
|
||||||
|
bean.phenomenon = row.getCell(2).stringCellValue
|
||||||
|
list.add(bean)
|
||||||
|
Log.e("jingo", bean.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roomAppDatabase.getScProblemTypeDao().insertOrUpdateList(list)
|
||||||
|
}
|
||||||
|
val sheet2 = workbook.getSheet("SC_ROOT_CAUSE_ANALYSIS")
|
||||||
|
sheet2?.let {
|
||||||
|
val rowCount: Int = it.physicalNumberOfRows // 获取行数
|
||||||
|
val list = mutableListOf<ScRootCauseAnalysisBean>()
|
||||||
|
for (i in 1 until rowCount) {
|
||||||
|
val row: Row = it.getRow(i) // 获取行
|
||||||
|
val cellCount: Int = row.physicalNumberOfCells // 获取列数
|
||||||
|
if (cellCount == 2) {
|
||||||
|
val bean = ScRootCauseAnalysisBean()
|
||||||
|
bean.problemLink = row.getCell(0).stringCellValue
|
||||||
|
bean.problemCause = row.getCell(1).stringCellValue
|
||||||
|
list.add(bean)
|
||||||
|
Log.e("jingo", bean.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roomAppDatabase.getScRootCauseAnalysisDao().insertOrUpdateList(list)
|
||||||
|
}
|
||||||
|
workbook.close()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
Log.e("jingo", e.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -5,6 +5,7 @@ import android.view.View.OnClickListener
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.navinfo.omqs.R
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RecyclerView 适配器基础类
|
* RecyclerView 适配器基础类
|
||||||
@ -26,6 +27,11 @@ abstract class BaseRecyclerViewAdapter<T>(var data: List<T> = listOf()) :
|
|||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
abstract fun getItemViewRes(position: Int): Int
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int {
|
||||||
|
return getItemViewRes(position)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
return data.size
|
return data.size
|
||||||
|
5
app/src/main/res/drawable/baseline_delete_forever_24.xml
Normal file
5
app/src/main/res/drawable/baseline_delete_forever_24.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#100F0F"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8.46,11.88l1.41,-1.41L12,12.59l2.12,-2.12 1.41,1.41L13.41,14l2.12,2.12 -1.41,1.41L12,15.41l-2.12,2.12 -1.41,-1.41L10.59,14l-2.13,-2.12zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/baseline_keyboard_voice_24.xml
Normal file
5
app/src/main/res/drawable/baseline_keyboard_voice_24.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#18FD00"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,15c1.66,0 2.99,-1.34 2.99,-3L15,6c0,-1.66 -1.34,-3 -3,-3S9,4.34 9,6v6c0,1.66 1.34,3 3,3zM17.3,12c0,3 -2.54,5.1 -5.3,5.1S6.7,15 6.7,12L5,12c0,3.42 2.72,6.23 6,6.72L11,22h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/baseline_save_24.xml
Normal file
5
app/src/main/res/drawable/baseline_save_24.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#100F0F"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
|
||||||
|
</vector>
|
@ -5,7 +5,6 @@
|
|||||||
tools:context=".ui.activity.map.MainActivity">
|
tools:context=".ui.activity.map.MainActivity">
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="mainActivity"
|
name="mainActivity"
|
||||||
type="com.navinfo.omqs.ui.activity.map.MainActivity" />
|
type="com.navinfo.omqs.ui.activity.map.MainActivity" />
|
||||||
@ -21,20 +20,65 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fitsSystemWindows="true">
|
android:fitsSystemWindows="true">
|
||||||
|
|
||||||
<include
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/map_view"
|
|
||||||
layout="@layout/map_view"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:mainActivity="@{mainActivity}"
|
tools:context=".ui.activity.map.MainActivity">
|
||||||
app:viewModel="@{viewModel}" />
|
|
||||||
|
<com.navinfo.collect.library.map.NIMapView
|
||||||
|
android:id="@+id/main_activity_map"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/main_activity_person_center"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:onClick="@{()->mainActivity.openMenu()}"
|
||||||
|
android:src="@drawable/baseline_person_24"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/main_activity_location"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:layout_marginBottom="80dp"
|
||||||
|
android:onClick="@{()->viewModel.onClickLocationButton()}"
|
||||||
|
android:src="@drawable/baseline_my_location_24"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/main_activity_voice"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
|
android:layout_marginBottom="120dp"
|
||||||
|
android:onClick="@{()->mainActivity.voiceOnclick()}"
|
||||||
|
android:src="@drawable/baseline_keyboard_voice_24"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent" />
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/main_activity_right_fragment"
|
||||||
|
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.3"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:navGraph="@navigation/right_fragment_nav_graph" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/main_activity_fragment"
|
android:id="@+id/main_activity_drawer_fragment"
|
||||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||||
android:layout_width="300dp"
|
android:layout_width="300dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="left"
|
android:layout_gravity="left"
|
||||||
app:navGraph="@navigation/nav_graph" />
|
app:navGraph="@navigation/left_drawer_nav_graph" />
|
||||||
</androidx.drawerlayout.widget.DrawerLayout>
|
</androidx.drawerlayout.widget.DrawerLayout>
|
||||||
</layout>
|
</layout>
|
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
<com.navinfo.collect.library.map.NIMapView
|
|
||||||
android:id="@+id/main_activity_map1"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
7
app/src/main/res/layout/fragment_empty.xml
Normal file
7
app/src/main/res/layout/fragment_empty.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:context=".ui.fragment.empty.EmptyFragment">
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
69
app/src/main/res/layout/fragment_evaluation_result.xml
Normal file
69
app/src/main/res/layout/fragment_evaluation_result.xml
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/white"
|
||||||
|
tools:context=".ui.fragment.evaluationresult.EvaluationResultFragment">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/evaluation_appbar_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/evaluation_bar"
|
||||||
|
style="@style/Widget.MaterialComponents.Toolbar.Surface"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="@color/default_blue"
|
||||||
|
app:menu="@menu/evaluation_bar_mean"
|
||||||
|
app:navigationIcon="@drawable/btn_back_xml"
|
||||||
|
app:title="测评结果" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/evaluation_appbar_layout">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="问题分类" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/evaluation_class_type"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:background="@drawable/fm_card_map_down_status_bg" />
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
android:id="@+id/evaluation_class_tab_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp" />
|
||||||
|
|
||||||
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
|
android:id="@+id/evaluation_viewpager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="5dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,99 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="#000000"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
style="@style/title_default_style"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="#553C3F41">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/btn_back"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:paddingBottom="@dimen/default_widget_padding"
|
|
||||||
android:paddingLeft="@dimen/default_widget_padding"
|
|
||||||
android:paddingRight="@dimen/default_widget_padding"
|
|
||||||
android:paddingTop="@dimen/default_widget_padding"
|
|
||||||
android:src="@drawable/btn_back_xml" />
|
|
||||||
|
|
||||||
<RadioGroup
|
|
||||||
android:id="@+id/rg_city"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<RadioButton
|
|
||||||
android:id="@+id/rb_manager"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@drawable/fm_card_map_btn_bg_line"
|
|
||||||
android:button="@null"
|
|
||||||
android:drawableLeft="@null"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingBottom="@dimen/default_widget_padding"
|
|
||||||
android:paddingLeft="@dimen/default_widget_padding"
|
|
||||||
android:paddingRight="@dimen/default_widget_padding"
|
|
||||||
android:paddingTop="@dimen/default_widget_padding"
|
|
||||||
android:text="下载管理"
|
|
||||||
android:textColor="@color/btn_blue_white"
|
|
||||||
android:textSize="18sp" />
|
|
||||||
|
|
||||||
<RadioButton
|
|
||||||
android:id="@+id/rb_city_list"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@drawable/fm_card_map_btn_bg_line"
|
|
||||||
android:button="@null"
|
|
||||||
android:checked="true"
|
|
||||||
android:drawableLeft="@null"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingBottom="@dimen/default_widget_padding"
|
|
||||||
android:paddingLeft="@dimen/default_widget_padding"
|
|
||||||
android:paddingRight="@dimen/default_widget_padding"
|
|
||||||
android:paddingTop="@dimen/default_widget_padding"
|
|
||||||
android:text="城市列表"
|
|
||||||
android:textColor="@color/btn_blue_white"
|
|
||||||
android:textSize="18sp" />
|
|
||||||
</RadioGroup>
|
|
||||||
</RelativeLayout>
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/edt_search"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
style="@style/input_blue_type"
|
|
||||||
android:hint="搜索"></EditText>
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_map_download_network_hint"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:text="网络错误,请检查网络后重试"></TextView>
|
|
||||||
<!-- <com.yanzhenjie.recyclerview.SwipeRecyclerView-->
|
|
||||||
<!-- android:id="@+id/lv_map_manager"-->
|
|
||||||
<!-- android:layout_width="match_parent"-->
|
|
||||||
<!-- android:visibility="invisible"-->
|
|
||||||
<!-- android:layout_height="match_parent">-->
|
|
||||||
<!-- </com.yanzhenjie.recyclerview.SwipeRecyclerView>-->
|
|
||||||
<!-- <com.yanzhenjie.recyclerview.SwipeRecyclerView-->
|
|
||||||
<!-- android:id="@+id/lv_map_city"-->
|
|
||||||
<!-- android:visibility="visible"-->
|
|
||||||
<!-- android:layout_width="match_parent"-->
|
|
||||||
<!-- android:layout_height="match_parent">-->
|
|
||||||
<!-- </com.yanzhenjie.recyclerview.SwipeRecyclerView>-->
|
|
||||||
</FrameLayout>
|
|
||||||
</LinearLayout>
|
|
@ -26,20 +26,13 @@
|
|||||||
android:text="城市列表" />
|
android:text="城市列表" />
|
||||||
</com.google.android.material.tabs.TabLayout>
|
</com.google.android.material.tabs.TabLayout>
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/offline_map_search"
|
|
||||||
style="@style/input_blue_type"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="搜索"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/offline_map_tab_layout" />
|
|
||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/offline_map_viewpager"
|
android:id="@+id/offline_map_viewpager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/offline_map_search" />
|
app:layout_constraintTop_toBottomOf="@id/offline_map_tab_layout" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/offline_map_back"
|
android:id="@+id/offline_map_back"
|
||||||
@ -51,4 +44,6 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="@id/offline_map_tab_layout"
|
app:layout_constraintBottom_toBottomOf="@id/offline_map_tab_layout"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/offline_map_tab_layout" />
|
app:layout_constraintTop_toTopOf="@id/offline_map_tab_layout" />
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -6,8 +6,19 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".ui.fragment.offlinemap.OfflineMapCityListFragment">
|
tools:context=".ui.fragment.offlinemap.OfflineMapCityListFragment">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/offline_map_search"
|
||||||
|
style="@style/input_blue_type"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="搜索"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/offline_map_city_list_recyclerview"
|
android:id="@+id/offline_map_city_list_recyclerview"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/offline_map_search" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -4,15 +4,11 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/default_red"
|
|
||||||
tools:context=".ui.fragment.offlinemap.OfflineMapStateListFragment">
|
tools:context=".ui.fragment.offlinemap.OfflineMapStateListFragment">
|
||||||
|
|
||||||
<TextView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:text="第一页"
|
android:id="@+id/offline_map_city_state_list_recyclerview"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -2,7 +2,7 @@
|
|||||||
<com.google.android.material.navigation.NavigationView xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.google.android.material.navigation.NavigationView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:context=".ui.fragment.personalcenter.PersonalCenterFragment"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="left"
|
android:layout_gravity="left"
|
||||||
|
15
app/src/main/res/layout/fragment_phenomenon.xml
Normal file
15
app/src/main/res/layout/fragment_phenomenon.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
tools:context="com.navinfo.omqs.ui.fragment.evaluationresult.PhenomenonFragment">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/phenomenon_recyclerview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,48 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<data>
|
|
||||||
<variable
|
|
||||||
name="mainActivity"
|
|
||||||
type="com.navinfo.omqs.ui.activity.map.MainActivity" />
|
|
||||||
|
|
||||||
<variable
|
|
||||||
name="viewModel"
|
|
||||||
type="com.navinfo.omqs.ui.activity.map.MainViewModel" />
|
|
||||||
</data>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".ui.activity.map.MainActivity">
|
|
||||||
|
|
||||||
<com.navinfo.collect.library.map.NIMapView
|
|
||||||
android:id="@+id/main_activity_map"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/main_activity_person_center"
|
|
||||||
android:layout_width="48dp"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:layout_marginLeft="20dp"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:onClick="@{()->mainActivity.openMenu()}"
|
|
||||||
android:src="@drawable/baseline_person_24"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/main_activity_location"
|
|
||||||
android:layout_width="48dp"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:layout_marginLeft="20dp"
|
|
||||||
android:layout_marginBottom="80dp"
|
|
||||||
android:onClick="@{()->viewModel.onClickLocationButton()}"
|
|
||||||
android:src="@drawable/baseline_my_location_24"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
</layout>
|
|
34
app/src/main/res/layout/temp.xml
Normal file
34
app/src/main/res/layout/temp.xml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/white"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/action_settings" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/evaluation_class_type"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp" />
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
android:id="@+id/evaluation_class_tab_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/default_blue">
|
||||||
|
<com.google.android.material.tabs.TabItem
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="下载管理" />
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabItem
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="城市列表" />
|
||||||
|
</com.google.android.material.tabs.TabLayout>
|
||||||
|
</LinearLayout>
|
11
app/src/main/res/layout/text_item_select.xml
Normal file
11
app/src/main/res/layout/text_item_select.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/item_id"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="5dp"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="18sp">
|
||||||
|
|
||||||
|
</TextView>
|
18
app/src/main/res/menu/evaluation_bar_mean.xml
Normal file
18
app/src/main/res/menu/evaluation_bar_mean.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/delete"
|
||||||
|
android:contentDescription="删除数据"
|
||||||
|
android:icon="@drawable/baseline_delete_forever_24"
|
||||||
|
android:title="删除"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/save"
|
||||||
|
android:contentDescription="保存数据"
|
||||||
|
android:icon="@drawable/baseline_save_24"
|
||||||
|
android:title="保存"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
</menu>
|
@ -15,9 +15,9 @@
|
|||||||
android:icon="@drawable/ic_baseline_import_export_24"
|
android:icon="@drawable/ic_baseline_import_export_24"
|
||||||
android:title="导入数据" />
|
android:title="导入数据" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/personal_center_menu_offline_map2"
|
android:id="@+id/personal_center_menu_import_yuan_data"
|
||||||
android:icon="@drawable/baseline_person_24"
|
android:icon="@drawable/ic_baseline_import_export_24"
|
||||||
android:title="menu_slideshow" />
|
android:title="导入元数据" />
|
||||||
</group>
|
</group>
|
||||||
<group
|
<group
|
||||||
android:id="@+id/group2"
|
android:id="@+id/group2"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/nav_graph"
|
android:id="@+id/left_drawer_nav_graph"
|
||||||
app:startDestination="@id/PersonalCenterFragment">
|
app:startDestination="@id/PersonalCenterFragment">
|
||||||
|
|
||||||
<fragment
|
<fragment
|
19
app/src/main/res/navigation/right_fragment_nav_graph.xml
Normal file
19
app/src/main/res/navigation/right_fragment_nav_graph.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/right_fragment_nav_graph"
|
||||||
|
app:startDestination="@id/EmptyFragment">
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/EmptyFragment"
|
||||||
|
android:name="com.navinfo.omqs.ui.fragment.empty.EmptyFragment"
|
||||||
|
android:label="空页面"
|
||||||
|
tools:layout="@layout/fragment_empty"></fragment>
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/EvaluationResultFragment"
|
||||||
|
android:name="com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultFragment"
|
||||||
|
android:label="评测页面"
|
||||||
|
tools:layout="@layout/fragment_evaluation_result"></fragment>
|
||||||
|
</navigation>
|
@ -1,5 +1,6 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "io.realm:realm-gradle-plugin:10.11.1"
|
classpath "io.realm:realm-gradle-plugin:10.11.1"
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'com.android.library'
|
id 'com.android.library'
|
||||||
id 'org.jetbrains.kotlin.android'
|
id 'org.jetbrains.kotlin.android'
|
||||||
|
id 'kotlin-parcelize' // 序列化
|
||||||
|
id 'kotlin-android'
|
||||||
|
id 'kotlin-kapt'
|
||||||
|
id 'realm-android'
|
||||||
}
|
}
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
apply plugin: 'kotlin-kapt'
|
|
||||||
apply plugin: 'realm-android'
|
|
||||||
|
|
||||||
|
ext.roomversion = "2.1.0"
|
||||||
ext.vtmVersion = "0.18.0"
|
ext.vtmVersion = "0.18.0"
|
||||||
ext.realm_version = '10.10.1'
|
ext.realm_version = '10.10.1'
|
||||||
ext.appcompatVersion = "1.3.0"
|
ext.appcompatVersion = "1.3.0"
|
||||||
@ -31,7 +33,7 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters "armeabi", "armeabi-v7a"
|
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,20 +55,22 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//configurations.all {
|
||||||
|
// resolutionStrategy {
|
||||||
|
// force 'com.intellij:annotations:13.0'
|
||||||
|
// }
|
||||||
|
//}
|
||||||
dependencies {
|
dependencies {
|
||||||
api fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
api fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
||||||
api files('libs/BaiduLBS_AndroidSDK_Lib.aar')
|
api files('libs/BaiduLBS_Android.jar')
|
||||||
implementation "androidx.appcompat:appcompat:$appcompatVersion"
|
|
||||||
implementation "com.google.android.material:material:$materialVersion"
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||||
implementation 'com.yanzhenjie:kalle:0.1.7'
|
implementation 'com.yanzhenjie:kalle:0.1.7'
|
||||||
|
|
||||||
// VTM依赖
|
// VTM依赖
|
||||||
implementation "net.sf.kxml:kxml2:2.3.0"
|
implementation "net.sf.kxml:kxml2:2.3.0"
|
||||||
implementation "org.slf4j:slf4j-api:1.7.28"
|
implementation 'org.slf4j:slf4j-api:2.0.7'
|
||||||
implementation "org.mapsforge:vtm:$vtmVersion"
|
implementation "org.mapsforge:vtm:$vtmVersion"
|
||||||
implementation "org.mapsforge:vtm-themes:$vtmVersion"
|
implementation "org.mapsforge:vtm-themes:$vtmVersion"
|
||||||
implementation "org.mapsforge:vtm-android:$vtmVersion"
|
implementation "org.mapsforge:vtm-android:$vtmVersion"
|
||||||
@ -94,30 +98,37 @@ dependencies {
|
|||||||
implementation "com.badlogicgames.gdx:gdx-backend-android:1.11.0"
|
implementation "com.badlogicgames.gdx:gdx-backend-android:1.11.0"
|
||||||
implementation "com.caverock:androidsvg:1.4"
|
implementation "com.caverock:androidsvg:1.4"
|
||||||
implementation "org.mapsforge:vtm-jts:$vtmVersion"
|
implementation "org.mapsforge:vtm-jts:$vtmVersion"
|
||||||
implementation "org.locationtech.jts:jts-core:1.18.2"
|
implementation 'org.locationtech.jts:jts-core:1.19.0'
|
||||||
implementation "com.squareup.okhttp3:okhttp:3.12.13"
|
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.11'
|
||||||
implementation "com.squareup.okio:okio:1.15.0"
|
implementation 'com.squareup.okio:okio:3.3.0'
|
||||||
|
|
||||||
implementation "com.fasterxml.jackson.core:jackson-annotations:2.9.9"
|
implementation "com.fasterxml.jackson.core:jackson-annotations:2.9.9"
|
||||||
implementation "com.fasterxml.jackson.core:jackson-core:2.9.9"
|
implementation "com.fasterxml.jackson.core:jackson-core:2.9.9"
|
||||||
implementation "com.fasterxml.jackson.core:jackson-databind:2.9.9"
|
implementation "com.fasterxml.jackson.core:jackson-databind:2.9.9"
|
||||||
implementation 'com.tencent.wcdb:room:1.0.8' // 代替 room-runtime,同时也不需要再引用 wcdb-android
|
|
||||||
|
|
||||||
implementation "androidx.sqlite:sqlite:2.0.1"
|
|
||||||
implementation "androidx.room:room-runtime:2.1.0"
|
|
||||||
annotationProcessor "androidx.room:room-compiler:2.1.0"
|
|
||||||
kapt "androidx.room:room-compiler:2.1.0"
|
|
||||||
androidTestImplementation 'androidx.room:room-testing:2.0.0'
|
|
||||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
|
|
||||||
kapt 'androidx.lifecycle:lifecycle-compiler:2.0.0'
|
|
||||||
implementation 'com.tencent.wcdb:wcdb-android:1.0.0'
|
|
||||||
implementation "androidx.core:core-ktx:1.8.0"
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
|
||||||
|
|
||||||
// 协程核心库
|
//room 数据库相关
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
|
api 'com.tencent.wcdb:room:1.1-19' // 代替 room-runtime,同时也不需要再引用 wcdb-android
|
||||||
// 协程Android支持库
|
api 'androidx.sqlite:sqlite-ktx:2.3.1'
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
|
api "androidx.room:room-runtime:2.5.1"
|
||||||
// 协程Java8支持库
|
api "androidx.room:room-ktx:2.5.1"
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.4'
|
annotationProcessor "androidx.room:room-compiler:2.5.1"
|
||||||
|
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
|
||||||
|
kapt 'android.arch.persistence.room:compiler:1.1.1'// compiler 需要用 room 的
|
||||||
|
kapt "androidx.room:room-compiler:2.5.1"
|
||||||
|
kapt "androidx.room:room-ktx:2.5.1"
|
||||||
|
|
||||||
|
// //分页加载
|
||||||
|
// api "androidx.room:room-paging:$roomversion"
|
||||||
|
// api "androidx.paging:paging-runtime-ktx:3.1.1"
|
||||||
|
|
||||||
|
androidTestImplementation "android.arch.persistence.room:testing:1.1.1"
|
||||||
|
api 'com.tencent.wcdb:wcdb-android:1.1-19'
|
||||||
|
|
||||||
|
// // 协程核心库
|
||||||
|
// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
|
||||||
|
// // 协程Android支持库
|
||||||
|
// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
|
||||||
|
// // 协程Java8支持库
|
||||||
|
// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.4'
|
||||||
}
|
}
|
BIN
collect-library/libs/BaiduLBS_Android.jar
Normal file
BIN
collect-library/libs/BaiduLBS_Android.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
collect-library/libs/arm64-v8a/libindoor.so
Normal file
BIN
collect-library/libs/arm64-v8a/libindoor.so
Normal file
Binary file not shown.
BIN
collect-library/libs/arm64-v8a/liblocSDK8b.so
Normal file
BIN
collect-library/libs/arm64-v8a/liblocSDK8b.so
Normal file
Binary file not shown.
BIN
collect-library/libs/armeabi-v7a/libindoor.so
Normal file
BIN
collect-library/libs/armeabi-v7a/libindoor.so
Normal file
Binary file not shown.
BIN
collect-library/libs/armeabi-v7a/liblocSDK8b.so
Normal file
BIN
collect-library/libs/armeabi-v7a/liblocSDK8b.so
Normal file
Binary file not shown.
BIN
collect-library/libs/x86/liblocSDK8b.so
Normal file
BIN
collect-library/libs/x86/liblocSDK8b.so
Normal file
Binary file not shown.
BIN
collect-library/libs/x86_64/liblocSDK8b.so
Normal file
BIN
collect-library/libs/x86_64/liblocSDK8b.so
Normal file
Binary file not shown.
@ -1,57 +1,57 @@
|
|||||||
package com.navinfo.collect.library.data.entity
|
//package com.navinfo.collect.library.data.entity
|
||||||
|
//
|
||||||
import io.realm.RealmObject
|
//import io.realm.RealmObject
|
||||||
import io.realm.annotations.PrimaryKey
|
//import io.realm.annotations.PrimaryKey
|
||||||
|
//
|
||||||
//enum class StatusEnum(val status: Int) {
|
////enum class StatusEnum(val status: Int) {
|
||||||
// NONE(0), WAITING(1), LOADING(2), PAUSE(3),
|
//// NONE(0), WAITING(1), LOADING(2), PAUSE(3),
|
||||||
// ERROR(4), DONE(5), UPDATE(6)
|
//// ERROR(4), DONE(5), UPDATE(6)
|
||||||
//}
|
////}
|
||||||
|
//
|
||||||
open class OfflineMapCityBean @JvmOverloads constructor(
|
//open class OfflineMapCityBean @JvmOverloads constructor(
|
||||||
@PrimaryKey var id: String = "",
|
// @PrimaryKey var id: String = "",
|
||||||
var fileName: String = "",
|
// var fileName: String = "",
|
||||||
var name: String = "",
|
// var name: String = "",
|
||||||
var url: String = "",
|
// var url: String = "",
|
||||||
var version: Long = 0L,
|
// var version: Long = 0L,
|
||||||
var fileSize: Long = 0L,
|
// var fileSize: Long = 0L,
|
||||||
var currentSize: Long = 0L,
|
// var currentSize: Long = 0L,
|
||||||
var status: Int = NONE
|
// var status: Int = NONE
|
||||||
) : RealmObject() {
|
//) : RealmObject() {
|
||||||
|
//
|
||||||
companion object Status{
|
// companion object Status{
|
||||||
const val NONE = 0 //无状态
|
// const val NONE = 0 //无状态
|
||||||
const val WAITING = 1 //等待中
|
// const val WAITING = 1 //等待中
|
||||||
const val LOADING = 2 //下载中
|
// const val LOADING = 2 //下载中
|
||||||
const val PAUSE = 3 //暂停
|
// const val PAUSE = 3 //暂停
|
||||||
const val ERROR = 4 //错误
|
// const val ERROR = 4 //错误
|
||||||
const val DONE = 5 //完成
|
// const val DONE = 5 //完成
|
||||||
const val UPDATE = 6 //有新版本要更新
|
// const val UPDATE = 6 //有新版本要更新
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// // status的转换对象
|
//// // status的转换对象
|
||||||
// var statusEnum: StatusEnum
|
//// var statusEnum: StatusEnum
|
||||||
// get() {
|
//// get() {
|
||||||
// return try {
|
//// return try {
|
||||||
// StatusEnum.values().find { it.status == status }!!
|
//// StatusEnum.values().find { it.status == status }!!
|
||||||
// } catch (e: IllegalArgumentException) {
|
//// } catch (e: IllegalArgumentException) {
|
||||||
// StatusEnum.NONE
|
//// StatusEnum.NONE
|
||||||
// }
|
//// }
|
||||||
// }
|
//// }
|
||||||
// set(value) {
|
//// set(value) {
|
||||||
// status = value.status
|
//// status = value.status
|
||||||
// }
|
//// }
|
||||||
|
//
|
||||||
fun getFileSizeText(): String {
|
// fun getFileSizeText(): String {
|
||||||
return if (fileSize < 1024.0)
|
// return if (fileSize < 1024.0)
|
||||||
"$fileSize B"
|
// "$fileSize B"
|
||||||
else if (fileSize < 1048576.0)
|
// else if (fileSize < 1048576.0)
|
||||||
"%.2f K".format(fileSize / 1024.0)
|
// "%.2f K".format(fileSize / 1024.0)
|
||||||
else if (fileSize < 1073741824.0)
|
// else if (fileSize < 1073741824.0)
|
||||||
"%.2f M".format(fileSize / 1048576.0)
|
// "%.2f M".format(fileSize / 1048576.0)
|
||||||
else
|
// else
|
||||||
"%.2f M".format(fileSize / 1073741824.0)
|
// "%.2f M".format(fileSize / 1073741824.0)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
}
|
//}
|
@ -1,43 +1,43 @@
|
|||||||
package com.navinfo.collect.library.data.entity
|
//package com.navinfo.collect.library.data.entity
|
||||||
|
//
|
||||||
import io.realm.RealmModel
|
//import io.realm.RealmModel
|
||||||
import io.realm.RealmObject
|
//import io.realm.RealmObject
|
||||||
import io.realm.annotations.PrimaryKey
|
//import io.realm.annotations.PrimaryKey
|
||||||
import io.realm.annotations.RealmClass
|
//import io.realm.annotations.RealmClass
|
||||||
|
//
|
||||||
@RealmClass
|
//@RealmClass
|
||||||
open class OfflineMapCityRealmObject: RealmModel {
|
//open class OfflineMapCityRealmObject: RealmModel {
|
||||||
@PrimaryKey
|
// @PrimaryKey
|
||||||
var id: String = ""
|
// var id: String = ""
|
||||||
var fileName: String=""
|
// var fileName: String=""
|
||||||
var name: String = ""
|
// var name: String = ""
|
||||||
var url: String = ""
|
// var url: String = ""
|
||||||
var version: Long = 0
|
// var version: Long = 0
|
||||||
var fileSize: Long = 0
|
// var fileSize: Long = 0
|
||||||
var currentSize:Long = 0
|
// var currentSize:Long = 0
|
||||||
var status:Int = 0
|
// var status:Int = 0
|
||||||
|
//
|
||||||
constructor(){
|
// constructor(){
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
constructor(
|
// constructor(
|
||||||
id: String,
|
// id: String,
|
||||||
fileName: String,
|
// fileName: String,
|
||||||
name: String,
|
// name: String,
|
||||||
url: String,
|
// url: String,
|
||||||
version: Long,
|
// version: Long,
|
||||||
fileSize: Long,
|
// fileSize: Long,
|
||||||
currentSize: Long,
|
// currentSize: Long,
|
||||||
status: Int
|
// status: Int
|
||||||
) {
|
// ) {
|
||||||
this.id = id
|
// this.id = id
|
||||||
this.fileName = fileName
|
// this.fileName = fileName
|
||||||
this.name = name
|
// this.name = name
|
||||||
this.url = url
|
// this.url = url
|
||||||
this.version = version
|
// this.version = version
|
||||||
this.fileSize = fileSize
|
// this.fileSize = fileSize
|
||||||
this.currentSize = currentSize
|
// this.currentSize = currentSize
|
||||||
this.status = status
|
// this.status = status
|
||||||
}
|
// }
|
||||||
}
|
//}
|
@ -1,17 +1,20 @@
|
|||||||
package com.navinfo.collect.library.map.handler
|
package com.navinfo.collect.library.map.handler
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Environment
|
|
||||||
import com.navinfo.collect.library.map.NIMapView
|
import com.navinfo.collect.library.map.NIMapView
|
||||||
import com.navinfo.collect.library.map.NIMapView.LAYER_GROUPS
|
|
||||||
import com.navinfo.collect.library.map.source.NavinfoMapRastorTileSource
|
import com.navinfo.collect.library.map.source.NavinfoMapRastorTileSource
|
||||||
|
import com.navinfo.collect.library.map.source.NavinfoMultiMapFileTileSource
|
||||||
import com.navinfo.collect.library.system.Constant
|
import com.navinfo.collect.library.system.Constant
|
||||||
import okhttp3.Cache
|
import okhttp3.Cache
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import org.oscim.layers.GroupLayer
|
||||||
import org.oscim.layers.Layer
|
import org.oscim.layers.Layer
|
||||||
import org.oscim.layers.LocationLayer
|
|
||||||
import org.oscim.layers.tile.bitmap.BitmapTileLayer
|
import org.oscim.layers.tile.bitmap.BitmapTileLayer
|
||||||
|
import org.oscim.layers.tile.buildings.BuildingLayer
|
||||||
|
import org.oscim.layers.tile.vector.VectorTileLayer
|
||||||
|
import org.oscim.layers.tile.vector.labeling.LabelLayer
|
||||||
import org.oscim.tiling.source.OkHttpEngine.OkHttpFactory
|
import org.oscim.tiling.source.OkHttpEngine.OkHttpFactory
|
||||||
|
import org.oscim.tiling.source.mapfile.MapFileTileSource
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,7 +22,8 @@ import java.io.File
|
|||||||
*/
|
*/
|
||||||
class LayerManagerHandler(context: Context, mapView: NIMapView) :
|
class LayerManagerHandler(context: Context, mapView: NIMapView) :
|
||||||
BaseHandler(context, mapView) {
|
BaseHandler(context, mapView) {
|
||||||
private var baseRasterLayer: Layer? = null
|
private var baseGroupLayer // 用于盛放所有基础底图的图层组,便于统一管理
|
||||||
|
: GroupLayer? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
initMap()
|
initMap()
|
||||||
@ -29,8 +33,10 @@ class LayerManagerHandler(context: Context, mapView: NIMapView) :
|
|||||||
* 初始化地图
|
* 初始化地图
|
||||||
*/
|
*/
|
||||||
private fun initMap() {
|
private fun initMap() {
|
||||||
switchBaseMapType(BASE_MAP_TYPE.CYCLE_MAP)
|
|
||||||
|
|
||||||
|
loadBaseMap()
|
||||||
|
mMapView.switchTileVectorLayerTheme(NIMapView.MAP_THEME.DEFAULT)
|
||||||
|
mMapView.vtmMap.updateMap()
|
||||||
// initVectorTileLayer()
|
// initVectorTileLayer()
|
||||||
// initMapLifeSource()
|
// initMapLifeSource()
|
||||||
}
|
}
|
||||||
@ -39,15 +45,60 @@ class LayerManagerHandler(context: Context, mapView: NIMapView) :
|
|||||||
/**
|
/**
|
||||||
* 切换基础底图样式
|
* 切换基础底图样式
|
||||||
*/
|
*/
|
||||||
fun switchBaseMapType(type: BASE_MAP_TYPE) {
|
fun loadBaseMap() {
|
||||||
if (baseRasterLayer != null) {
|
|
||||||
mMapView.vtmMap.layers().remove(baseRasterLayer)
|
if (baseGroupLayer == null) {
|
||||||
baseRasterLayer = null
|
baseGroupLayer = GroupLayer(mMapView.vtmMap)
|
||||||
mMapView.vtmMap.updateMap()
|
addLayer(baseGroupLayer!!, NIMapView.LAYER_GROUPS.BASE)
|
||||||
|
}
|
||||||
|
baseGroupLayer?.let {
|
||||||
|
for (layer in it.layers) {
|
||||||
|
removeLayer(layer)
|
||||||
|
}
|
||||||
|
it.layers.clear()
|
||||||
|
val builder = OkHttpClient.Builder()
|
||||||
|
val urlTileSource: NavinfoMultiMapFileTileSource =
|
||||||
|
NavinfoMultiMapFileTileSource.builder()
|
||||||
|
.httpFactory(OkHttpFactory(builder)) //.locale("en")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
// Cache the tiles into file system
|
||||||
|
val cacheDirectory = File(Constant.MAP_PATH, "cache")
|
||||||
|
val cacheSize = 200 * 1024 * 1024 // 10 MB
|
||||||
|
val cache = Cache(cacheDirectory, cacheSize.toLong())
|
||||||
|
builder.cache(cache)
|
||||||
|
|
||||||
|
// val headerMap = HashMap<String, String>()
|
||||||
|
// headerMap["token"] = ""//Constant.TOKEN
|
||||||
|
// urlTileSource.setHttpRequestHeaders(headerMap)
|
||||||
|
val baseLayer = VectorTileLayer(mMapView.vtmMap, urlTileSource)
|
||||||
|
|
||||||
|
val baseMapFolder = File("${Constant.MAP_PATH}offline")
|
||||||
|
|
||||||
|
if (baseMapFolder.exists()) {
|
||||||
|
val dirFileList = baseMapFolder.listFiles()
|
||||||
|
if (dirFileList != null && dirFileList.isNotEmpty()) {
|
||||||
|
for (mapFile in dirFileList) {
|
||||||
|
if (!mapFile.isFile || !mapFile.name.endsWith(".map")) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val mTileSource = MapFileTileSource()
|
||||||
|
mTileSource.setPreferredLanguage("zh")
|
||||||
|
if (mTileSource.setMapFile(mapFile.absolutePath)) {
|
||||||
|
urlTileSource.add(mTileSource)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
baseLayer.tileSource = urlTileSource
|
||||||
|
it.layers.add(baseLayer)
|
||||||
|
it.layers.add(BuildingLayer(mMapView.vtmMap, baseLayer))
|
||||||
|
it.layers.add(LabelLayer(mMapView.vtmMap, baseLayer))
|
||||||
|
for (layer in it.layers) {
|
||||||
|
addLayer(layer, NIMapView.LAYER_GROUPS.BASE)
|
||||||
|
}
|
||||||
|
mMapView.updateMap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
baseRasterLayer = getRasterTileLayer(type.url, type.tilePath, true)
|
|
||||||
addLayer(baseRasterLayer!!, LAYER_GROUPS.BASE)
|
|
||||||
mMapView.updateMap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRasterTileLayer(
|
private fun getRasterTileLayer(
|
||||||
@ -61,16 +112,13 @@ class LayerManagerHandler(context: Context, mapView: NIMapView) :
|
|||||||
.httpFactory(OkHttpFactory(builder)).build()
|
.httpFactory(OkHttpFactory(builder)).build()
|
||||||
// 如果使用缓存
|
// 如果使用缓存
|
||||||
if (useCache) {
|
if (useCache) {
|
||||||
val cacheDirectory: File =
|
val cacheDirectory =
|
||||||
File(Constant.MAP_PATH, "tiles-raster")
|
File(Constant.MAP_PATH, "cache")
|
||||||
val cacheSize = 300 * 1024 * 1024 // 300 MB
|
val cacheSize = 300 * 1024 * 1024 // 300 MB
|
||||||
val cache = Cache(cacheDirectory, cacheSize.toLong())
|
val cache = Cache(cacheDirectory, cacheSize.toLong())
|
||||||
builder.cache(cache)
|
builder.cache(cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
// mTileSource.setHttpEngine(new OkHttpEngine.OkHttpFactory(builder));
|
|
||||||
// mTileSource.setHttpRequestHeaders(Collections.singletonMap("User-Agent", "vtm-android-example"));
|
|
||||||
// mTileSource.setCache(new TileCache(mContext, defaultDir, url.substring(url.indexOf(":")+1)));
|
|
||||||
return BitmapTileLayer(mMapView.vtmMap, mTileSource)
|
return BitmapTileLayer(mMapView.vtmMap, mTileSource)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,7 @@ import com.navinfo.collect.library.map.NIMapView
|
|||||||
import org.oscim.layers.LocationLayer
|
import org.oscim.layers.LocationLayer
|
||||||
|
|
||||||
|
|
||||||
class LocationLayerHandler(context: Context, mapView: NIMapView) :
|
class LocationLayerHandler(context: Context, mapView: NIMapView) : BaseHandler(context, mapView) {
|
||||||
BaseHandler(context, mapView) {
|
|
||||||
|
|
||||||
private var mCurrentLocation: BDLocation? = null
|
private var mCurrentLocation: BDLocation? = null
|
||||||
private var bFirst = true
|
private var bFirst = true
|
||||||
@ -55,13 +54,11 @@ class LocationLayerHandler(context: Context, mapView: NIMapView) :
|
|||||||
val errorCode = it.locType
|
val errorCode = it.locType
|
||||||
mCurrentLocation = it
|
mCurrentLocation = it
|
||||||
mLocationLayer.setPosition(
|
mLocationLayer.setPosition(
|
||||||
it.latitude,
|
it.latitude, it.longitude, it.radius
|
||||||
it.longitude,
|
|
||||||
it.radius
|
|
||||||
)
|
)
|
||||||
//第一次定位成功显示当前位置
|
//第一次定位成功显示当前位置
|
||||||
if (this.bFirst) {
|
if (this.bFirst) {
|
||||||
animateToCurrentPosition()
|
animateToCurrentPosition(16.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -97,9 +94,7 @@ class LocationLayerHandler(context: Context, mapView: NIMapView) :
|
|||||||
// locationOption.setOpenAutoNotifyMode()
|
// locationOption.setOpenAutoNotifyMode()
|
||||||
//设置打开自动回调位置模式,该开关打开后,期间只要定位SDK检测到位置变化就会主动回调给开发者
|
//设置打开自动回调位置模式,该开关打开后,期间只要定位SDK检测到位置变化就会主动回调给开发者
|
||||||
locationOption.setOpenAutoNotifyMode(
|
locationOption.setOpenAutoNotifyMode(
|
||||||
1000,
|
1000, 1, LocationClientOption.LOC_SENSITIVITY_HIGHT
|
||||||
1,
|
|
||||||
LocationClientOption.LOC_SENSITIVITY_HIGHT
|
|
||||||
)
|
)
|
||||||
//需将配置好的LocationClientOption对象,通过setLocOption方法传递给LocationClient对象使用
|
//需将配置好的LocationClientOption对象,通过setLocOption方法传递给LocationClient对象使用
|
||||||
locationClient.locOption = locationOption
|
locationClient.locOption = locationOption
|
||||||
@ -130,12 +125,21 @@ class LocationLayerHandler(context: Context, mapView: NIMapView) :
|
|||||||
/**
|
/**
|
||||||
* 回到当前位置
|
* 回到当前位置
|
||||||
*/
|
*/
|
||||||
fun animateToCurrentPosition()
|
fun animateToCurrentPosition(zoom: Double) {
|
||||||
{
|
|
||||||
mCurrentLocation?.run {
|
mCurrentLocation?.run {
|
||||||
val mapPosition = mMapView.vtmMap.mapPosition;
|
val mapPosition = mMapView.vtmMap.mapPosition
|
||||||
mapPosition.setPosition(this.latitude, this.longitude);
|
mapPosition.zoom = zoom
|
||||||
mMapView.vtmMap.animator().animateTo(300, mapPosition);
|
mapPosition.setPosition(this.latitude, this.longitude)
|
||||||
|
mMapView.vtmMap.animator().animateTo(300, mapPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun animateToCurrentPosition() {
|
||||||
|
mCurrentLocation?.run {
|
||||||
|
val mapPosition = mMapView.vtmMap.mapPosition
|
||||||
|
mapPosition.setPosition(this.latitude, this.longitude)
|
||||||
|
mMapView.vtmMap.animator().animateTo(300, mapPosition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,8 +147,7 @@ class LocationLayerHandler(context: Context, mapView: NIMapView) :
|
|||||||
/**
|
/**
|
||||||
* 实现定位回调
|
* 实现定位回调
|
||||||
*/
|
*/
|
||||||
private class MyLocationListener(callback: (BDLocation) -> Unit) :
|
private class MyLocationListener(callback: (BDLocation) -> Unit) : BDAbstractLocationListener() {
|
||||||
BDAbstractLocationListener() {
|
|
||||||
val call = callback;
|
val call = callback;
|
||||||
override fun onReceiveLocation(location: BDLocation) {
|
override fun onReceiveLocation(location: BDLocation) {
|
||||||
call(location)
|
call(location)
|
||||||
|
@ -1,39 +1,38 @@
|
|||||||
package com.navinfo.collect.library.map.source;
|
package com.navinfo.collect.library.map.source;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.navinfo.collect.library.system.Constant;
|
||||||
|
|
||||||
import org.oscim.core.BoundingBox;
|
import org.oscim.core.BoundingBox;
|
||||||
import org.oscim.core.MapElement;
|
|
||||||
import org.oscim.core.Tag;
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.tiling.ITileDataSource;
|
import org.oscim.tiling.ITileDataSource;
|
||||||
import org.oscim.tiling.OverzoomTileDataSource;
|
import org.oscim.tiling.OverzoomTileDataSource;
|
||||||
import org.oscim.tiling.source.UrlTileSource;
|
import org.oscim.tiling.source.UrlTileSource;
|
||||||
import org.oscim.tiling.source.geojson.GeojsonTileSource;
|
|
||||||
import org.oscim.tiling.source.mapfile.IMapFileTileSource;
|
import org.oscim.tiling.source.mapfile.IMapFileTileSource;
|
||||||
import org.oscim.tiling.source.mapfile.MapDatabase;
|
import org.oscim.tiling.source.mapfile.MapDatabase;
|
||||||
import org.oscim.tiling.source.mapfile.MapFileTileSource;
|
import org.oscim.tiling.source.mapfile.MapFileTileSource;
|
||||||
import org.oscim.utils.FastMath;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*com.navinfo.map.source
|
*com.nmp.map.source
|
||||||
*zhjch
|
*zhjch
|
||||||
*2021/9/17
|
*2021/9/17
|
||||||
*9:46
|
*9:46
|
||||||
*说明()
|
*说明()
|
||||||
*/
|
*/
|
||||||
public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements IMapFileTileSource {
|
public class NavinfoMultiMapFileTileSource extends UrlTileSource implements IMapFileTileSource {
|
||||||
|
|
||||||
// private static final String DEFAULT_URL = "http://cmp-gateway-sp9-port.ayiqdpfs.cloud.app.ncloud.navinfo.com/maponline/map/online";
|
private static final String DEFAULT_URL = "http://c.tile.opencyclemap.org/cycle";
|
||||||
private static final String DEFAULT_URL = "http://epohvqjxts85k6u-port.ayiqdpfs.cloud.app.ncloud.navinfo.com/map/online/geoJson";
|
|
||||||
private static final String DEFAULT_PATH = "x={X}&y={Y}&z={Z}";
|
private static final String DEFAULT_PATH = "/{Z}}/{X}/{Y}.png";
|
||||||
private static final TileUrlFormatter mTileUrlFormatter = URL_FORMATTER;
|
private static final TileUrlFormatter mTileUrlFormatter = URL_FORMATTER;
|
||||||
|
|
||||||
|
|
||||||
@ -67,7 +66,6 @@ public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements
|
|||||||
public String getTileUrl(Tile tile) {
|
public String getTileUrl(Tile tile) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(DEFAULT_URL).append("?").append(mTileUrlFormatter.formatTilePath(this, tile));
|
sb.append(DEFAULT_URL).append("?").append(mTileUrlFormatter.formatTilePath(this, tile));
|
||||||
System.out.println(sb.toString());
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,66 +123,13 @@ public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements
|
|||||||
mapDatabase.restrictToZoomRange(zoomLevels[0], zoomLevels[1]);
|
mapDatabase.restrictToZoomRange(zoomLevels[0], zoomLevels[1]);
|
||||||
multiMapDatabase.add(mapDatabase);
|
multiMapDatabase.add(mapDatabase);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
Log.e("jingo", e.getMessage());
|
||||||
log.debug(e.getMessage());
|
log.debug(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// return new NavinfoMultiMapDatabase(this, new NavinfoVectorTileDecoder(locale), getHttpEngine());
|
// return new NavinfoMultiMapDatabase(this, new NavinfoVectorTileDecoder(locale), getHttpEngine());
|
||||||
return new OverzoomTileDataSource(multiMapDatabase, mOverZoom);
|
return new OverzoomTileDataSource(multiMapDatabase, mOverZoom);
|
||||||
}
|
}
|
||||||
private static Map<String, Tag> mappings = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
private static Tag addMapping(String key, String val) {
|
|
||||||
Tag tag = new Tag(key, val);
|
|
||||||
mappings.put(key + "=" + val, tag);
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
|
|
||||||
boolean hasName = false;
|
|
||||||
String fallbackName = null;
|
|
||||||
|
|
||||||
for (Map.Entry<String, Object> entry : properties.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
Object value = entry.getValue();
|
|
||||||
String val = (value instanceof String) ? (String) value : String.valueOf(value);
|
|
||||||
|
|
||||||
if (key.startsWith(Tag.KEY_NAME)) {
|
|
||||||
int len = key.length();
|
|
||||||
if (len == 4) {
|
|
||||||
fallbackName = val;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (len < 7)
|
|
||||||
continue;
|
|
||||||
if (locale.equals(key.substring(5))) {
|
|
||||||
hasName = true;
|
|
||||||
mapElement.tags.add(new Tag(Tag.KEY_NAME, val, false));
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Tag tag = mappings.get(key + "=" + val);
|
|
||||||
if (tag == null)
|
|
||||||
tag = addMapping(key, val);
|
|
||||||
mapElement.tags.add(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasName && fallbackName != null)
|
|
||||||
mapElement.tags.add(new Tag(Tag.KEY_NAME, fallbackName, false));
|
|
||||||
|
|
||||||
// Calculate height of building parts
|
|
||||||
if (!properties.containsKey(Tag.KEY_HEIGHT)) {
|
|
||||||
if (properties.containsKey(Tag.KEY_VOLUME) && properties.containsKey(Tag.KEY_AREA)) {
|
|
||||||
Object volume = properties.get(Tag.KEY_VOLUME);
|
|
||||||
String volumeStr = (volume instanceof String) ? (String) volume : String.valueOf(volume);
|
|
||||||
Object area = properties.get(Tag.KEY_AREA);
|
|
||||||
String areaStr = (area instanceof String) ? (String) area : String.valueOf(area);
|
|
||||||
float height = Float.parseFloat(volumeStr) / Float.parseFloat(areaStr);
|
|
||||||
String heightStr = String.valueOf(FastMath.round2(height));
|
|
||||||
mapElement.tags.add(new Tag(Tag.KEY_HEIGHT, heightStr, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenResult open() {
|
public OpenResult open() {
|
||||||
@ -194,8 +139,10 @@ public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements
|
|||||||
if (result != OpenResult.SUCCESS)
|
if (result != OpenResult.SUCCESS)
|
||||||
openResult = result;
|
openResult = result;
|
||||||
}
|
}
|
||||||
if(openResult != OpenResult.SUCCESS)
|
if(openResult != OpenResult.SUCCESS) {
|
||||||
return super.open();
|
|
||||||
|
return super.open();
|
||||||
|
}
|
||||||
return openResult;
|
return openResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@ import java.util.Map;
|
|||||||
|
|
||||||
public class Constant {
|
public class Constant {
|
||||||
|
|
||||||
|
//服务地址
|
||||||
|
public static String URL_BASE = "http://cmp-gateway-sp9-port.ayiqdpfs.cloud.app.ncloud.navinfo.com/";
|
||||||
|
|
||||||
public static String MAP_PATH = Environment.getExternalStorageDirectory() + "/map/";
|
public static String MAP_PATH = Environment.getExternalStorageDirectory() + "/map/";
|
||||||
|
|
||||||
public static void setVisibleTypeMap(Map<String, Boolean> visibleTypeMap) {
|
public static void setVisibleTypeMap(Map<String, Boolean> visibleTypeMap) {
|
||||||
|
@ -1,30 +1,32 @@
|
|||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
|
||||||
google()
|
google()
|
||||||
|
gradlePluginPortal()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url 'https://jitpack.io' }
|
|
||||||
maven { url "https://maven.aliyun.com/repository/google" }
|
maven { url "https://maven.aliyun.com/repository/google" }
|
||||||
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
|
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
|
||||||
maven { url 'https://maven.aliyun.com/repository/public' }
|
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||||
maven { url 'https://maven.aliyun.com/repository/jcenter' }
|
maven { url 'https://maven.aliyun.com/repository/jcenter' }
|
||||||
maven { url 'https://download.flutter.io' }
|
maven { url 'https://maven.aliyun.com/repository/central' }
|
||||||
maven { url 'https://storage.googleapis.com/download.flutter.io' }
|
maven { url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
repositories {
|
repositories {
|
||||||
|
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
maven { url 'https://jitpack.io' }
|
|
||||||
maven { url "https://maven.aliyun.com/repository/google" }
|
maven { url "https://maven.aliyun.com/repository/google" }
|
||||||
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
|
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
|
||||||
maven { url 'https://maven.aliyun.com/repository/public' }
|
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||||
maven { url 'https://maven.aliyun.com/repository/jcenter' }
|
maven { url 'https://maven.aliyun.com/repository/jcenter' }
|
||||||
maven { url 'https://download.flutter.io' }
|
maven { url 'https://maven.aliyun.com/repository/central' }
|
||||||
maven { url 'https://storage.googleapis.com/download.flutter.io' }
|
maven { url 'https://jitpack.io' }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rootProject.name = "OMQualityInspection"
|
rootProject.name = "OMQualityInspection"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user