From fa4ad254a59097f3f6bb6d1eb47c797c776cdb1e Mon Sep 17 00:00:00 2001 From: squallzhjch Date: Thu, 6 Apr 2023 10:46:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0realm=20=E5=9C=A8=E7=A6=BB?= =?UTF-8?q?=E7=BA=BF=E5=9C=B0=E5=9B=BE=E4=B8=AD=E7=9A=84=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/navinfo/omqs/Constant.kt | 12 + .../java/com/navinfo/omqs/OMQSApplication.kt | 7 +- .../navinfo/omqs/bean/OfflineMapCityBean.kt | 45 ---- .../omqs/bean/OfflineMapCityRealmObject.kt | 17 -- .../com/navinfo/omqs/hilt/GlobalModule.kt | 21 +- .../navinfo/omqs/hilt/MainActivityModule.kt | 8 +- .../com/navinfo/omqs/http/NetworkService.kt | 3 +- .../navinfo/omqs/http/NetworkServiceImpl.kt | 2 +- .../omqs/http/RetrofitNetworkServiceAPI.kt | 4 +- .../OfflineMapDownloadManager.kt | 40 ++- .../OfflineMapDownloadScope.kt | 233 ++++++------------ .../com/navinfo/omqs/tools/FileManager.kt | 95 +++++++ .../navinfo/omqs/tools/RealmCoroutineScope.kt | 57 +++++ .../java/com/navinfo/omqs/ui/MainActivity.kt | 6 - .../omqs/ui/activity/login/LoginActivity.kt | 6 + .../omqs/ui/activity/login/LoginViewModel.kt | 93 +++---- .../omqs/ui/activity/map/MainActivity.kt | 1 - .../omqs/ui/activity/map/MainViewModel.kt | 1 - .../offlinemap/OfflineMapCityListAdapter.kt | 34 ++- .../offlinemap/OfflineMapCityListFragment.kt | 1 - .../offlinemap/OfflineMapCityListViewModel.kt | 37 ++- .../fragment/offlinemap/OfflineMapFragment.kt | 1 - .../offlinemap/OfflineMapStateListFragment.kt | 1 - .../personalcenter/PersonalCenterFragment.kt | 6 - .../navinfo/omqs/ui/other/BaseViewHolder.kt | 1 + .../navinfo/omqs/ui/widget/MyProgressBar.kt | 5 +- .../library/data/entity/OfflineMapCityBean.kt | 65 ++--- .../data/handler/DataNiLocationHandler.kt | 1 - .../collect/library/map/NIMapController.kt | 3 - 29 files changed, 422 insertions(+), 384 deletions(-) delete mode 100644 app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityBean.kt delete mode 100644 app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityRealmObject.kt create mode 100644 app/src/main/java/com/navinfo/omqs/tools/FileManager.kt create mode 100644 app/src/main/java/com/navinfo/omqs/tools/RealmCoroutineScope.kt diff --git a/app/src/main/java/com/navinfo/omqs/Constant.kt b/app/src/main/java/com/navinfo/omqs/Constant.kt index 446bfc16..306ff4e3 100644 --- a/app/src/main/java/com/navinfo/omqs/Constant.kt +++ b/app/src/main/java/com/navinfo/omqs/Constant.kt @@ -8,8 +8,20 @@ class Constant { * sd卡根目录 */ lateinit var ROOT_PATH: String + + /** + * 地图目录 + */ lateinit var MAP_PATH: String + + /** + * 数据目录 + */ lateinit var DATA_PATH: String + + /** + * 离线地图目录 + */ lateinit var OFFLINE_MAP_PATH: String /** diff --git a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt index 7205a54d..27e26fa3 100644 --- a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt +++ b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt @@ -1,13 +1,18 @@ package com.navinfo.omqs import android.app.Application +import android.util.Log +import com.navinfo.omqs.tools.FileManager import dagger.hilt.android.HiltAndroidApp import io.realm.Realm +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import java.io.File @HiltAndroidApp class OMQSApplication : Application() { override fun onCreate() { + FileManager.initRootDir(this) super.onCreate() - Realm.init(this) } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityBean.kt b/app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityBean.kt deleted file mode 100644 index d4485441..00000000 --- a/app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityBean.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.navinfo.omqs.bean - -import io.realm.RealmObject - -enum class StatusEnum(val status: Int) { - NONE(0), WAITING(1), LOADING(2), PAUSE(3), - ERROR(4), DONE(5), UPDATE(6) -} - -open class OfflineMapCityBean{ - 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 = StatusEnum.NONE.status - - // status的转换对象 - var statusEnum:StatusEnum - get() { - return try { - StatusEnum.values().find { it.status == status }!! - } catch (e: IllegalArgumentException) { - StatusEnum.NONE - } - } - set(value) { - status = value.status - } - - constructor() : super() - - 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) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityRealmObject.kt b/app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityRealmObject.kt deleted file mode 100644 index 92461d60..00000000 --- a/app/src/main/java/com/navinfo/omqs/bean/OfflineMapCityRealmObject.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.navinfo.omqs.bean - -import io.realm.RealmObject -import io.realm.annotations.PrimaryKey - - -open class OfflineMapCityRealmObject(){ - @PrimaryKey - var id: String = "" - var fileName: String="" - var name: String = "" - var url: String = "" - var version: Long = 0 - var fileSize: Long = 0 - var currentSize:Long = 0 - var status:Int = 0 -} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/hilt/GlobalModule.kt b/app/src/main/java/com/navinfo/omqs/hilt/GlobalModule.kt index ccfa89dc..4ace2b64 100644 --- a/app/src/main/java/com/navinfo/omqs/hilt/GlobalModule.kt +++ b/app/src/main/java/com/navinfo/omqs/hilt/GlobalModule.kt @@ -6,11 +6,13 @@ import com.google.gson.Gson import com.navinfo.omqs.Constant import com.navinfo.omqs.OMQSApplication import com.navinfo.omqs.http.RetrofitNetworkServiceAPI +import com.navinfo.omqs.tools.RealmCoroutineScope import dagger.Lazy import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.* import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit @@ -25,11 +27,11 @@ import javax.inject.Singleton @InstallIn(SingletonComponent::class) class GlobalModule { -// @Singleton -// @Provides -// fun provideApplication(application: Application): OMQSApplication { -// return application as OMQSApplication -// } + @Singleton + @Provides + fun provideApplication(application: Application): OMQSApplication { + return application as OMQSApplication + } /** * 注入 网络OKHttp 对象 @@ -92,4 +94,13 @@ class GlobalModule { fun provideNetworkService(retrofit: Retrofit): RetrofitNetworkServiceAPI { return retrofit.create(RetrofitNetworkServiceAPI::class.java) } + + /** + * realm 注册 + */ + @Provides + @Singleton + fun provideRealmService(context: Application): RealmCoroutineScope { + return RealmCoroutineScope(context) + } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt b/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt index 5587be3e..8560c38b 100644 --- a/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt +++ b/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt @@ -1,14 +1,13 @@ package com.navinfo.omqs.hilt -import android.content.Context import com.navinfo.collect.library.map.NIMapController import com.navinfo.omqs.http.RetrofitNetworkServiceAPI import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager +import com.navinfo.omqs.tools.RealmCoroutineScope import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.components.ActivityRetainedComponent -import dagger.hilt.android.qualifiers.ActivityContext import dagger.hilt.android.scopes.ActivityRetainedScoped @InstallIn(ActivityRetainedComponent::class) @@ -28,9 +27,10 @@ class MainActivityModule { @ActivityRetainedScoped @Provides fun providesOfflineMapDownloadManager( - networkServiceAPI: RetrofitNetworkServiceAPI + networkServiceAPI: RetrofitNetworkServiceAPI, + realmManager: RealmCoroutineScope ): OfflineMapDownloadManager = - OfflineMapDownloadManager( networkServiceAPI) + OfflineMapDownloadManager(networkServiceAPI, realmManager) /** * 实验失败,这样创建,viewmodel不会在activity销毁的时候同时销毁 diff --git a/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt b/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt index 8ed34846..eb4a6103 100644 --- a/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt +++ b/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt @@ -1,6 +1,7 @@ package com.navinfo.omqs.http -import com.navinfo.omqs.bean.OfflineMapCityBean +import com.navinfo.collect.library.data.entity.OfflineMapCityBean + /** * 网络访问 业务接口 diff --git a/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt b/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt index 4a67bf83..bbcafc3e 100644 --- a/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt +++ b/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt @@ -1,6 +1,6 @@ package com.navinfo.omqs.http -import com.navinfo.omqs.bean.OfflineMapCityBean +import com.navinfo.collect.library.data.entity.OfflineMapCityBean import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import javax.inject.Inject diff --git a/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt b/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt index 34fa2cdf..4bea1858 100644 --- a/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt +++ b/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt @@ -1,14 +1,12 @@ package com.navinfo.omqs.http -import androidx.lifecycle.LiveData -import com.navinfo.omqs.bean.OfflineMapCityBean +import com.navinfo.collect.library.data.entity.OfflineMapCityBean import okhttp3.ResponseBody import retrofit2.Response import retrofit2.http.GET import retrofit2.http.Header import retrofit2.http.Streaming import retrofit2.http.Url -import java.util.concurrent.Flow /** * retrofit2 网络请求接口 diff --git a/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadManager.kt b/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadManager.kt index d38896f0..e4aa57e1 100644 --- a/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadManager.kt +++ b/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadManager.kt @@ -1,23 +1,17 @@ package com.navinfo.omqs.http.offlinemapdownload -import android.content.Context -import android.text.TextUtils -import android.util.Log import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.Observer -import com.navinfo.omqs.Constant -import com.navinfo.omqs.bean.OfflineMapCityBean +import com.navinfo.collect.library.data.entity.OfflineMapCityBean import com.navinfo.omqs.http.RetrofitNetworkServiceAPI -import dagger.hilt.android.qualifiers.ActivityContext -import kotlinx.coroutines.cancel +import com.navinfo.omqs.tools.RealmCoroutineScope import java.util.concurrent.ConcurrentHashMap -import javax.inject.Inject /** * 管理离线地图下载 */ -class OfflineMapDownloadManager @Inject constructor( - private val netApi: RetrofitNetworkServiceAPI +class OfflineMapDownloadManager( + val netApi: RetrofitNetworkServiceAPI, val realmManager: RealmCoroutineScope ) { /** * 最多同时下载数量 @@ -94,33 +88,27 @@ class OfflineMapDownloadManager @Inject constructor( scopeMap[id]?.start() } - fun cancel(id: String) { - taskScopeMap.remove(id) - scopeMap[id]?.cancelTask() - } fun addTask(cityBean: OfflineMapCityBean) { - if (scopeMap.containsKey(cityBean.id)) { - return - } else { - scopeMap[cityBean.id] = OfflineMapDownloadScope(this, netApi, cityBean) + if (!scopeMap.containsKey(cityBean.id)) { + scopeMap[cityBean.id] = OfflineMapDownloadScope(this, cityBean) } } fun observer( - id: String, - lifecycleOwner: LifecycleOwner, - observer: Observer + id: String, lifecycleOwner: LifecycleOwner, observer: Observer ) { if (scopeMap.containsKey(id)) { - val downloadScope = scopeMap[id] - downloadScope?.let { - downloadScope.observer(lifecycleOwner, observer) - } + scopeMap[id]!!.observer(lifecycleOwner, observer) + } + } + + fun removeObserver(id: String) { + if (scopeMap.containsKey(id)) { + scopeMap[id]!!.removeObserver() } } - } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadScope.kt b/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadScope.kt index c518b504..0821f8c0 100644 --- a/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadScope.kt +++ b/app/src/main/java/com/navinfo/omqs/http/offlinemapdownload/OfflineMapDownloadScope.kt @@ -4,14 +4,13 @@ import android.util.Log import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Observer +import com.navinfo.collect.library.data.entity.OfflineMapCityBean import com.navinfo.omqs.Constant -import com.navinfo.omqs.bean.OfflineMapCityBean -import com.navinfo.omqs.http.RetrofitNetworkServiceAPI import kotlinx.coroutines.* import java.io.File import java.io.IOException +import java.io.InputStream import java.io.RandomAccessFile -import kotlin.coroutines.EmptyCoroutineContext /** * 代表一个下载任务 @@ -22,11 +21,9 @@ import kotlin.coroutines.EmptyCoroutineContext */ class OfflineMapDownloadScope( private val downloadManager: OfflineMapDownloadManager, - private val netApi: RetrofitNetworkServiceAPI, - val cityBean: OfflineMapCityBean - + val cityBean: OfflineMapCityBean, ) : - CoroutineScope by CoroutineScope(EmptyCoroutineContext) { + CoroutineScope by CoroutineScope(Dispatchers.IO) { /** *下载任务,用来取消的 */ @@ -35,10 +32,11 @@ class OfflineMapDownloadScope( /** * 管理观察者,同时只有一个就行了 */ - private var observer: Observer? = null +// private var observer: Observer? = null + private var lifecycleOwner: LifecycleOwner? = null /** - * + *通知UI更新 */ private val downloadData = MutableLiveData() @@ -46,39 +44,6 @@ class OfflineMapDownloadScope( downloadData.value = cityBean } - /** - * 开始任务的下载 - * [OfflineMapCityBean]是在协程中进行创建的,它的创建会优先从数据库和本地文件获取,但这种操作是异步的,详情请看init代码块 - * 我们需要通过观察者观察[OfflineMapCityBean]来得知它是否已经创建完成,只有当他创建完成且不为空(如果创建完成,它一定不为空) - * 才可以交由[OfflineMapDownloadManager]进行下载任务的启动 - * 任务的开始可能并不是立即的,任务会受到[OfflineMapDownloadManager]的管理 - * - * 这段原来代码没看懂:要触发 Observer 得观察的对象[OfflineMapCityBean]发生变化才行,原demo里没找到livedata的变化也触发了onChange,这里根本触发不了 - * - * 找到原因了:是[cityBean]根本没有设置到liveData中,但是还是不用这样了,因为cityBean是一定创建好了的 - */ - //原代码 -// fun start() { -// var observer: Observer? = null -// observer = Observer { cityBean -> -// Log.e("jingo","Observer 创建了,bean 为null吗?$cityBean") -// cityBean?.let { -// observer?.let { -// Log.e("jingo","Observer 这里为什么要解除观察?") -// downloadData.removeObserver(it) -// } -// Log.e("jingo","Observer 状态 ${cityBean.status} ") -// when (cityBean.status) { -// -// OfflineMapCityBean.PAUSE, OfflineMapCityBean.ERROR, OfflineMapCityBean.NONE -> { -// change(OfflineMapCityBean.WAITING) -// downloadManager.launchScope(this@OfflineMapDownloadScope) -// } -// } -// } -// } -// downloadData.observeForever(observer) -// } //改进的代码 fun start() { change(OfflineMapCityBean.WAITING) @@ -91,6 +56,7 @@ class OfflineMapDownloadScope( */ fun pause() { downloadJob?.cancel("pause") + change(OfflineMapCityBean.PAUSE) } /** @@ -98,20 +64,12 @@ class OfflineMapDownloadScope( * 请不要尝试在外部调用此方法,那样会脱离[OfflineMapDownloadManager]的管理 */ fun launch() { - downloadJob = launch { - try { - download() - change(OfflineMapCityBean.DONE) - } catch (e: Throwable) { - Log.e("jingo DownloadScope", "error:${e.message}") - if (e.message == "pause") { - change(OfflineMapCityBean.PAUSE) - } else { - change(OfflineMapCityBean.ERROR) - } - } finally { - downloadManager.launchNext(cityBean.id) - } + downloadJob = launch() { + Log.e("jingo", "启动下载1") + download() + Log.e("jingo", "启动下载2") + downloadManager.launchNext(cityBean.id) + Log.e("jingo", "启动下载3") } } @@ -120,9 +78,7 @@ class OfflineMapDownloadScope( * 是否是等待任务 */ fun isWaiting(): Boolean { - val downloadInfo = downloadData.value - downloadInfo ?: return false - return downloadInfo.status == OfflineMapCityBean.WAITING + return cityBean.status == OfflineMapCityBean.WAITING } /** @@ -130,126 +86,91 @@ class OfflineMapDownloadScope( * @param status [OfflineMapCityBean.Status] */ private fun change(status: Int) { - downloadData.value?.let { - it.status = status - downloadData.postValue(it) + if (cityBean.status != status || status == OfflineMapCityBean.LOADING) { + cityBean.status = status + downloadData.postValue(cityBean) + + downloadManager.realmManager.launch { + downloadManager.realmManager.insertOrUpdate(cityBean) + } } } /** * 添加下载任务观察者 */ - fun observer(lifecycleOwner: LifecycleOwner, ob: Observer) { - if (observer != null) { - downloadData.removeObserver(observer!!) - } - this.observer = ob - downloadData.observe(lifecycleOwner, observer!!) + fun observer(owner: LifecycleOwner, ob: Observer) { + removeObserver() + this.lifecycleOwner = owner + downloadData.observe(owner, ob) } /** * 下载文件 */ - private suspend fun download() = withContext(context = Dispatchers.IO, block = { - - val downloadInfo = downloadData.value ?: throw IOException("jingo Download info is null") - //创建离线地图 下载文件夹,.map文件夹的下一级 - val fileDir = File("${Constant.OFFLINE_MAP_PATH}download") - if (!fileDir.exists()) { - fileDir.mkdirs() - } - //遍历文件夹,找到对应的省市.map文件 - val files = fileDir.listFiles() - for (item in files) { - //用id找到对应的文件 - if (item.isFile && item.name.startsWith(downloadInfo.id)) { - //判断文件的版本号是否一致 - if (item.name.contains("_${downloadInfo.version}.map")) { - //都一致,说明文件已经下载完成,不用再次下载 - change(OfflineMapCityBean.DONE) - return@withContext - }else{ - - } - break - } - } - - //查看下.map文件夹在不在 - val fileMap = File("${Constant.OFFLINE_MAP_PATH}${downloadInfo.fileName}") - val fileTemp = - File("${Constant.OFFLINE_MAP_PATH}download/${downloadInfo.id}_${downloadInfo.version}") - - - if (fileTemp.exists()) { - - } - - if (!fileMap.exists()) { - } - - change(OfflineMapCityBean.LOADING) - - - val startPosition = downloadInfo.currentSize - //验证断点有效性 - if (startPosition < 0) throw IOException("jingo Start position less than zero") - //下载的文件是否已经被删除 -// if (startPosition > 0 && !TextUtils.isEmpty(downloadInfo.path)) -// if (!File(downloadInfo.path).exists()) throw IOException("File does not exist") - val response = netApi.retrofitDownLoadFile( - start = "bytes=$startPosition-", - url = downloadInfo.url - ) - val responseBody = response.body() - - responseBody ?: throw IOException("jingo ResponseBody is null") - //文件长度 - downloadInfo.fileSize = responseBody.contentLength() - //保存的文件名称 -// if (TextUtils.isEmpty(downloadInfo.fileName)) -// downloadInfo.fileName = UrlUtils.getUrlFileName(downloadInfo.url) - -// //验证下载完成的任务与实际文件的匹配度 -// if (startPosition == downloadInfo.fileSize && startPosition > 0) { -// if (file.exists() && startPosition == file.length()) { -// change(OfflineMapCityBean.DONE) -// return@withContext -// } else throw IOException("jingo The content length is not the same as the file length") -// } - //写入文件 - val randomAccessFile = RandomAccessFile(fileTemp, "rwd") - randomAccessFile.seek(startPosition) -// if (downloadInfo.currentSize == 0L) { -// randomAccessFile.setLength(downloadInfo.fileSize) -// } - downloadInfo.currentSize = startPosition - val inputStream = responseBody.byteStream() - val bufferSize = 1024 * 2 - val buffer = ByteArray(bufferSize) + private suspend fun download() { + var inputStream: InputStream? = null + var randomAccessFile: RandomAccessFile? = null try { + //创建离线地图 下载文件夹,.map文件夹的下一级 + val fileDir = File("${Constant.OFFLINE_MAP_PATH}download") + if (!fileDir.exists()) { + fileDir.mkdirs() + } + + val fileTemp = + File("${Constant.OFFLINE_MAP_PATH}download/${cityBean.id}_${cityBean.version}") + val startPosition = cityBean.currentSize + //验证断点有效性 + if (startPosition < 0) throw IOException("jingo Start position less than zero") + val response = downloadManager.netApi.retrofitDownLoadFile( + start = "bytes=$startPosition-", + url = cityBean.url + ) + val responseBody = response.body() + change(OfflineMapCityBean.LOADING) + responseBody ?: throw IOException("jingo ResponseBody is null") + //写入文件 + randomAccessFile = RandomAccessFile(fileTemp, "rwd") + randomAccessFile.seek(startPosition) + cityBean.currentSize = startPosition + inputStream = responseBody.byteStream() + val bufferSize = 1024 * 2 + val buffer = ByteArray(bufferSize) + var readLength = 0 - while (isActive) { + while (downloadJob?.isActive == true) { readLength = inputStream.read(buffer) if (readLength != -1) { randomAccessFile.write(buffer, 0, readLength) - downloadInfo.currentSize += readLength + cityBean.currentSize += readLength change(OfflineMapCityBean.LOADING) } else { break } } + + Log.e("jingo", "文件下载完成 ${cityBean.currentSize} == ${cityBean.fileSize}") + if (cityBean.currentSize == cityBean.fileSize) { + val res = + fileTemp.renameTo(File("${Constant.OFFLINE_MAP_PATH}${cityBean.fileName}")) + Log.e("jingo", "文件下载完成 修改文件 $res") + change(OfflineMapCityBean.DONE) + } else { + change(OfflineMapCityBean.PAUSE) + } + } catch (e: Throwable) { + change(OfflineMapCityBean.ERROR) } finally { - inputStream.close() - randomAccessFile.close() + inputStream?.close() + randomAccessFile?.close() } - }) - - /** - * - */ - private fun checkFile(){ - } + fun removeObserver() { + lifecycleOwner?.let { + downloadData.removeObservers(it) + null + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/tools/FileManager.kt b/app/src/main/java/com/navinfo/omqs/tools/FileManager.kt new file mode 100644 index 00000000..e40972ee --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/tools/FileManager.kt @@ -0,0 +1,95 @@ +package com.navinfo.omqs.tools + +import android.content.Context +import android.util.Log +import com.navinfo.collect.library.data.entity.OfflineMapCityBean +import com.navinfo.omqs.Constant +import java.io.File + +class FileManager { + companion object { + //初始化数据文件夹 + fun initRootDir(context:Context){ + // 在SD卡创建项目目录 + val sdCardPath = context.getExternalFilesDir(null) + sdCardPath?.let { + Constant.ROOT_PATH = sdCardPath.absolutePath + Constant.MAP_PATH = Constant.ROOT_PATH + "/map/" + Constant.OFFLINE_MAP_PATH = Constant.MAP_PATH + "offline/" + val file = File(Constant.MAP_PATH) + if (!file.exists()) { + file.mkdirs() + Constant.DATA_PATH = Constant.ROOT_PATH + "/data/" + with(File(Constant.MAP_PATH)) { + if (!this.exists()) this.mkdirs() + } + with(File(Constant.DATA_PATH)) { + if (!this.exists()) this.mkdirs() + } + }else{ + Constant.DATA_PATH = Constant.ROOT_PATH + "/data/" + } + } + } + + /** + * 检查离线地图文件 + */ + suspend fun checkOfflineMapFileInfo(cityBean: OfflineMapCityBean) { + //访问离线地图文件夹 + val fileDir = File("${Constant.OFFLINE_MAP_PATH}") + //如果连本地文件夹还没有,就不用修改任何数据了 + if (!fileDir.exists()) { + return + } + //访问离线地图临时下载文件夹 + val fileTempDir = File("${Constant.OFFLINE_MAP_PATH}download/") + //是否有一份.map文件了 + var mapFile: File? = null + //文件夹里文件挨个访问 + for (item in fileDir.listFiles()) { + //先找到对应的省市文件,例如:540000_西藏自治区_20230401195018.map",以id开头 + if (item.isFile && item.name.startsWith(cityBean.id)) { + //如果本地文件与从网络获取到版本号一致,表示这个文件已经下载完毕,不用处理了 + if (item.name.contains("_${cityBean.version}.map")) { + cityBean.status = OfflineMapCityBean.DONE + return + } + //文件存在,版本号不对应,留给下面流程处理 + mapFile = item + break + } + } + //临时下载文件夹 + if (fileTempDir.exists()) { + for (item in fileTempDir.listFiles()) { + //先找到对应的省市文件,例如:540000_20230401195018",以id开头 + if (item.isFile && item.name.startsWith(cityBean.id)) { + //如果本地文件与从网络获取到版本号一致,表示这个文件已经在下载列表中 + if (item.name == "${cityBean.id}_${cityBean.version}") { + //如果这个临时文件的大小和下载大小是一致的,说明已经下载完了,但是在下载环节没有更名移动成功,需要重命名和移动文件夹 + if (item.length() == cityBean.fileSize) { + //移动更名文件后删除旧数据,修改状态 + if (item.renameTo(File("${Constant.OFFLINE_MAP_PATH}${cityBean.fileName}"))) { + //删除旧版本数据 + mapFile?.delete() + cityBean.status = OfflineMapCityBean.DONE + return + } + } else { // 临时文件大小和目标不一致,说明下载了一半 + cityBean.status = OfflineMapCityBean.PAUSE + cityBean.currentSize = item.length() + return + } + } else { //虽然省市id开头一致,但是版本号不一致,说明之前版本下载了一部分,现在要更新了,原来下载的文件直接删除 + cityBean.status = OfflineMapCityBean.UPDATE + item.delete() + return + } + break + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/tools/RealmCoroutineScope.kt b/app/src/main/java/com/navinfo/omqs/tools/RealmCoroutineScope.kt new file mode 100644 index 00000000..70880896 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/tools/RealmCoroutineScope.kt @@ -0,0 +1,57 @@ +package com.navinfo.omqs.tools + +import android.app.Application +import com.navinfo.collect.library.data.entity.OfflineMapCityBean +import com.navinfo.omqs.Constant +import io.realm.Realm +import io.realm.RealmConfiguration +import io.realm.RealmModel +import io.realm.Sort +import io.realm.kotlin.where +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.newSingleThreadContext +import java.io.File + +class RealmCoroutineScope(context: Application) : + CoroutineScope by CoroutineScope(newSingleThreadContext("RealmThread")) { + lateinit var realm: Realm + + init { + launch { + Realm.init(context) + 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) + realm = Realm.getDefaultInstance() + } + } + + suspend fun getOfflineCityList(): List { + var list: List = mutableListOf() + realm.executeTransaction { + val objects = realm.where().findAll().sort("id", Sort.ASCENDING) + list = realm.copyFromRealm(objects) + } + return list + } + + suspend fun insertOrUpdate(objects: Collection?) { + realm.executeTransaction { + realm.insertOrUpdate(objects) + } + } + + suspend fun insertOrUpdate(realmModel: RealmModel?) { + realm.executeTransaction { + realm.insertOrUpdate(realmModel) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/MainActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/MainActivity.kt index b0293ec3..6bad71e2 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/MainActivity.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/MainActivity.kt @@ -3,15 +3,9 @@ package com.navinfo.omqs.ui import android.content.Intent import android.os.Bundle import androidx.core.view.WindowCompat -import androidx.navigation.findNavController import androidx.navigation.ui.AppBarConfiguration -import androidx.navigation.ui.navigateUp -import androidx.navigation.ui.setupActionBarWithNavController -import android.view.Menu -import android.view.MenuItem import com.github.k1rakishou.fsaf.FileChooser import com.github.k1rakishou.fsaf.callback.FSAFActivityCallbacks -import com.navinfo.omqs.R import com.navinfo.omqs.databinding.ActivityMainBinding import com.navinfo.omqs.ui.activity.PermissionsActivity diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginActivity.kt index 36c50b0b..061fe8dc 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginActivity.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginActivity.kt @@ -13,10 +13,13 @@ import com.navinfo.omqs.R import com.navinfo.omqs.databinding.ActivityLoginBinding import com.navinfo.omqs.ui.activity.PermissionsActivity import com.navinfo.omqs.ui.activity.map.MainActivity +import dagger.hilt.android.AndroidEntryPoint /** * 登陆页面 */ + +@AndroidEntryPoint class LoginActivity : PermissionsActivity() { private lateinit var binding: ActivityLoginBinding @@ -65,6 +68,9 @@ class LoginActivity : PermissionsActivity() { loginDialog?.dismiss() loginDialog = null } + LoginStatus.LOGIN_STATUS_NET_OFFLINE_MAP -> { + loginDialog("检查离线地图...") + } } } diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt index 26072081..76496b0d 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt @@ -5,17 +5,17 @@ import android.util.Log import android.view.View import android.widget.Toast import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.Observer import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.navinfo.omqs.Constant import com.navinfo.omqs.bean.LoginUserBean -import io.realm.Realm -import io.realm.RealmConfiguration +import com.navinfo.omqs.http.NetResult +import com.navinfo.omqs.http.NetworkService +import com.navinfo.omqs.tools.FileManager +import com.navinfo.omqs.tools.RealmCoroutineScope +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.* import okio.IOException -import java.io.File -import java.math.BigInteger +import javax.inject.Inject enum class LoginStatus { /** @@ -23,6 +23,11 @@ enum class LoginStatus { */ LOGIN_STATUS_NET_LOADING, + /** + * 访问离线地图列表 + */ + LOGIN_STATUS_NET_OFFLINE_MAP, + /** * 初始化文件夹 */ @@ -49,7 +54,10 @@ enum class LoginStatus { LOGIN_STATUS_CANCEL, } -class LoginViewModel( +@HiltViewModel +class LoginViewModel @Inject constructor( + private val networkService: NetworkService, + private val realmManager: RealmCoroutineScope ) : ViewModel() { //用户信息 val loginUser: MutableLiveData = MutableLiveData() @@ -63,17 +71,6 @@ class LoginViewModel( loginUser.value = LoginUserBean(username = "admin", password = "123456") } - private fun initRealm() { - 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() - Constant.realm = Realm.getInstance(config) - } /** * 处理注册按钮 @@ -113,46 +110,56 @@ class LoginViewModel( //文件夹初始化 try { loginStatus.postValue(LoginStatus.LOGIN_STATUS_FOLDER_INIT) - createRootFolder(context) + createUserFolder(context) // 初始化Realm - initRealm() } catch (e: IOException) { loginStatus.postValue(LoginStatus.LOGIN_STATUS_FOLDER_FAILURE) } + //假装解压文件等 delay(1000) - loginStatus.postValue(LoginStatus.LOGIN_STATUS_SUCCESS) + loginStatus.postValue(LoginStatus.LOGIN_STATUS_NET_OFFLINE_MAP) + when (val result = networkService.getOfflineMapCityList()) { + is NetResult.Success -> { -// } + if (result.data != null) { + for (cityBean in result.data) { + FileManager.checkOfflineMapFileInfo(cityBean) + } + realmManager.launch { + realmManager.insertOrUpdate(result.data) + } + } + } + is NetResult.Error -> { + withContext(Dispatchers.Main) { + Toast.makeText(context, "${result.exception.message}", Toast.LENGTH_SHORT) + .show() + } + } + is NetResult.Failure -> { + withContext(Dispatchers.Main) { + Toast.makeText(context, "${result.code}:${result.msg}", Toast.LENGTH_SHORT) + .show() + } + } + NetResult.Loading -> {} + } + loginStatus.postValue(LoginStatus.LOGIN_STATUS_SUCCESS) } - + /** + * 创建用户目录 + */ @Throws(IOException::class) - private fun createRootFolder(context: Context) { - // 在SD卡创建项目目录 - val sdCardPath = context.getExternalFilesDir(null) - sdCardPath?.let { - Constant.ROOT_PATH = sdCardPath.absolutePath - Constant.MAP_PATH = Constant.ROOT_PATH + "/map/" - Constant.OFFLINE_MAP_PATH = Constant.MAP_PATH + "offline/" - val file = File(Constant.MAP_PATH) - if (!file.exists()) { - file.mkdirs() - Constant.DATA_PATH = Constant.ROOT_PATH + "/data/" - with(File(Constant.MAP_PATH)) { - if(!this.exists()) this.mkdirs() - } - with(File(Constant.DATA_PATH)) { - if(!this.exists()) this.mkdirs() - } - } + private fun createUserFolder(context: Context) { + // 在SD卡创建用户目录,解压资源等 } /** * 取消登录 */ fun cancelLogin() { - Log.e("jingo", "取消了?${Thread.currentThread().name}") jobLogin?.let { it.cancel() loginStatus.value = LoginStatus.LOGIN_STATUS_CANCEL @@ -163,6 +170,4 @@ class LoginViewModel( super.onCleared() cancelLogin() } - - } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt index 0ec5416c..4126123b 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt @@ -69,7 +69,6 @@ class MainActivity : BaseActivity() { super.onDestroy() mapController.mMapView.onDestroy() mapController.locationLayerHandler.stopLocation() - Log.e("jingo", "MainActivity 销毁") } override fun onResume() { diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt index 722baf7a..c052a0f7 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt @@ -25,7 +25,6 @@ class MainViewModel @Inject constructor( } override fun onCleared() { - Log.e("jingo","MainViewModel 被释放了") super.onCleared() } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListAdapter.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListAdapter.kt index 8894d104..d27594bd 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListAdapter.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListAdapter.kt @@ -6,8 +6,8 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.lifecycle.Observer +import com.navinfo.collect.library.data.entity.OfflineMapCityBean import com.navinfo.omqs.R -import com.navinfo.omqs.bean.OfflineMapCityBean import com.navinfo.omqs.databinding.AdapterOfflineMapCityBinding import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter @@ -32,14 +32,16 @@ class OfflineMapCityListAdapter @Inject constructor( val cityBean = data[it.tag as Int] when (cityBean.status) { OfflineMapCityBean.NONE, OfflineMapCityBean.UPDATE, OfflineMapCityBean.PAUSE, OfflineMapCityBean.ERROR -> { + Log.e("jingo", "开始下载 ${cityBean.status}") downloadManager.start(cityBean.id) } OfflineMapCityBean.LOADING, OfflineMapCityBean.WAITING -> { + Log.e("jingo", "暂停 ${cityBean.status}") downloadManager.pause(cityBean.id) } -// OfflineMapCityBean.WAITING->{ -// downloadManager.cancel(cityBean.id) -// } + else -> { + Log.e("jingo", "暂停 ${cityBean.status}") + } } } } @@ -50,24 +52,38 @@ class OfflineMapCityListAdapter @Inject constructor( return BaseViewHolder(viewBinding) } + override fun onViewRecycled(holder: BaseViewHolder) { + super.onViewRecycled(holder) + //页面滑动时会用holder重构页面,但是对进度条的监听回调会一直返回,扰乱UI,所以当当前holder去重构的时候,移除监听 + downloadManager.removeObserver(holder.tag) + } + override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { val binding: AdapterOfflineMapCityBinding = holder.viewBinding as AdapterOfflineMapCityBinding //牺牲性能立刻刷新UI,解决闪烁 这里不用 // binding.executePendingBindings() val cityBean = data[position] + //tag 方便onclick里拿到数据 + holder.tag = cityBean.id + changeViews(binding, cityBean) + downloadManager.addTask(cityBean) + downloadManager.observer(cityBean.id, holder, DownloadObserver(cityBean.id, binding)) binding.offlineMapDownloadBtn.tag = position binding.offlineMapDownloadBtn.setOnClickListener(downloadBtnClick) binding.offlineMapCityName.text = cityBean.name binding.offlineMapCitySize.text = cityBean.getFileSizeText() - downloadManager.addTask(cityBean) - changeViews(binding, cityBean) - downloadManager.observer(cityBean.id, holder) { - if (cityBean.id == it.id) - changeViews(binding, it) + } + + inner class DownloadObserver(val id: String, val binding: AdapterOfflineMapCityBinding) : + Observer { + override fun onChanged(t: OfflineMapCityBean?) { + if (id == t?.id) + changeViews(binding, t) } } + private fun changeViews(binding: AdapterOfflineMapCityBinding, cityBean: OfflineMapCityBean) { binding.offlineMapProgress.progress = (cityBean.currentSize * 100 / cityBean.fileSize).toInt() diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListFragment.kt index 1baa5823..5d64468d 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListFragment.kt @@ -57,6 +57,5 @@ class OfflineMapCityListFragment : Fragment() { override fun onDestroyView() { super.onDestroyView() _binding = null - Log.e("jingo", "OfflineMapCityListFragment onDestroyView") } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListViewModel.kt index 93ddba13..1dbd04f0 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapCityListViewModel.kt @@ -1,16 +1,18 @@ package com.navinfo.omqs.ui.fragment.offlinemap -import android.app.Application import android.content.Context -import android.widget.Toast import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.navinfo.omqs.http.NetResult -import com.navinfo.omqs.http.NetworkService -import com.navinfo.omqs.bean.OfflineMapCityBean +import com.navinfo.collect.library.data.entity.OfflineMapCityBean +import com.navinfo.omqs.tools.FileManager +import com.navinfo.omqs.tools.RealmCoroutineScope import dagger.hilt.android.lifecycle.HiltViewModel 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.launch import javax.inject.Inject @@ -19,8 +21,7 @@ import javax.inject.Inject */ @HiltViewModel class OfflineMapCityListViewModel @Inject constructor( - private val networkService: NetworkService, - @ApplicationContext val context: Context + @ApplicationContext val context: Context, ) : ViewModel() { val cityListLiveData = MutableLiveData>() @@ -29,21 +30,15 @@ class OfflineMapCityListViewModel @Inject constructor( * 去获取离线地图列表 */ fun getCityList() { - viewModelScope.launch { - when (val result = networkService.getOfflineMapCityList()) { - is NetResult.Success -> { - cityListLiveData.postValue(result.data?.sortedBy { bean -> bean.id }) - } - is NetResult.Error -> { - Toast.makeText(context, "${result.exception.message}", Toast.LENGTH_SHORT) - .show() - } - is NetResult.Failure -> { - Toast.makeText(context, "${result.code}:${result.msg}", Toast.LENGTH_SHORT) - .show() - } - NetResult.Loading -> {} + viewModelScope.launch(Dispatchers.IO) { + val realm = Realm.getDefaultInstance() + val objects = realm.where().findAll().sort("id", Sort.ASCENDING) + val list = realm.copyFromRealm(objects) + realm.close() + for (item in list) { + FileManager.checkOfflineMapFileInfo(item) } + cityListLiveData.postValue(list) } } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapFragment.kt index ee60b969..8f9da1e1 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapFragment.kt @@ -61,6 +61,5 @@ class OfflineMapFragment : Fragment() { override fun onDestroyView() { super.onDestroyView() _binding = null - Log.e("jingo","OfflineMapFragment onDestroyView") } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapStateListFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapStateListFragment.kt index 59285dcf..b4ae37f7 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapStateListFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/offlinemap/OfflineMapStateListFragment.kt @@ -33,6 +33,5 @@ class OfflineMapStateListFragment : Fragment() { override fun onDestroyView() { super.onDestroyView() _binding = null - Log.e("jingo","OfflineMapStateListFragment onDestroyView") } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt index 37d7f1dd..e0d21450 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt @@ -3,21 +3,16 @@ package com.navinfo.omqs.ui.fragment.personalcenter import android.content.Intent import android.net.Uri import android.os.Bundle -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.activity.viewModels import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels -import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.get import androidx.navigation.fragment.findNavController import com.blankj.utilcode.util.UriUtils import com.github.k1rakishou.fsaf.FileChooser import com.github.k1rakishou.fsaf.callback.FSAFActivityCallbacks import com.github.k1rakishou.fsaf.callback.FileChooserCallback -import com.google.android.material.snackbar.Snackbar import com.navinfo.omqs.R import com.navinfo.omqs.databinding.FragmentPersonalCenterBinding @@ -42,7 +37,6 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - Log.e("jingo", "NIMapController PersonalCenterFragment onViewCreated") binding.root.setNavigationItemSelectedListener { when (it.itemId) { R.id.personal_center_menu_offline_map -> diff --git a/app/src/main/java/com/navinfo/omqs/ui/other/BaseViewHolder.kt b/app/src/main/java/com/navinfo/omqs/ui/other/BaseViewHolder.kt index e6f4d62c..2544a7c0 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/other/BaseViewHolder.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/other/BaseViewHolder.kt @@ -14,6 +14,7 @@ import androidx.viewbinding.ViewBinding open class BaseViewHolder(val viewBinding: ViewBinding) : RecyclerView.ViewHolder(viewBinding.root), LifecycleOwner { private val lifecycleRegistry = LifecycleRegistry(this) + var tag = "" init { // dataBinding.lifecycleOwner = this diff --git a/app/src/main/java/com/navinfo/omqs/ui/widget/MyProgressBar.kt b/app/src/main/java/com/navinfo/omqs/ui/widget/MyProgressBar.kt index aab03188..b4a9fd7f 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/widget/MyProgressBar.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/widget/MyProgressBar.kt @@ -62,9 +62,10 @@ class MyProgressBar : ProgressBar { // int x = (getWidth()/2) - rect.centerX(); // int y = (getHeight()/2) - rect.centerY(); var x = (width * rate).toInt() - if (x == width) { + val dx = width - rect.right + if (x > dx) { // 如果为百分之百则在左边绘制。 - x = width - rect.right + x = dx } mPaint.textSize = 24f val y: Int = 10 - rect.top diff --git a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/OfflineMapCityBean.kt b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/OfflineMapCityBean.kt index e3791593..9d1f54fe 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/OfflineMapCityBean.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/OfflineMapCityBean.kt @@ -3,31 +3,44 @@ package com.navinfo.collect.library.data.entity import io.realm.RealmObject import io.realm.annotations.PrimaryKey -enum class StatusEnum(val status: Int) { - NONE(0), WAITING(1), LOADING(2), PAUSE(3), - ERROR(4), DONE(5), UPDATE(6) -} +//enum class StatusEnum(val status: Int) { +// NONE(0), WAITING(1), LOADING(2), PAUSE(3), +// ERROR(4), DONE(5), UPDATE(6) +//} -open 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 =0) : RealmObject(){ - // status的转换对象 - var statusEnum:StatusEnum - get() { - return try { - StatusEnum.values().find { it.status == status }!! - } catch (e: IllegalArgumentException) { - StatusEnum.NONE - } - } - set(value) { - status = value.status - } +open 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 +) : RealmObject() { + + 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) @@ -40,9 +53,5 @@ open class OfflineMapCityBean @JvmOverloads constructor(@PrimaryKey var id: Stri "%.2f M".format(fileSize / 1073741824.0) } -// constructor(){ -// -// } -// } \ No newline at end of file diff --git a/collect-library/src/main/java/com/navinfo/collect/library/data/handler/DataNiLocationHandler.kt b/collect-library/src/main/java/com/navinfo/collect/library/data/handler/DataNiLocationHandler.kt index 2b0c66fb..5415baee 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/data/handler/DataNiLocationHandler.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/data/handler/DataNiLocationHandler.kt @@ -91,7 +91,6 @@ DataNiLocationHandler(context: Context, dataBase: MapLifeDataBase) : ) mDataBase.niLocationDao.delete(niLocation); } catch (e: Throwable) { - Log.e("jingo", "删除数据报错 ${e.message}"); Handler(Looper.getMainLooper()).post { callback.invoke(false, "${e.message}") } diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/NIMapController.kt b/collect-library/src/main/java/com/navinfo/collect/library/map/NIMapController.kt index fb6e7c1f..72ccc8dc 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/map/NIMapController.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/NIMapController.kt @@ -37,8 +37,5 @@ class NIMapController { mapView.setOptions(options) } - fun print() { - Log.e("jingo", "NIMapController 哈希code ${hashCode()}") - } }