Commit c74bbdeb authored by Vladislav Bogdashkin's avatar Vladislav Bogdashkin 🎣

integrate download service

parent 696b8464
......@@ -60,6 +60,10 @@ android {
targetCompatibility 1.8
sourceCompatibility 1.8
}
lintOptions {
disable 'BinaryOperationInTimber'
}
}
kapt {
......
......@@ -19,7 +19,7 @@ interface IBigantoApi {
fun downloadFile(uri: String, headers: Map<String, String>?): Flowable<ResponseBody>
// fun getToursFiles(tour_ids: List<Int>, resolution: String): Flowable<Map<String, List<TourFileRaw>>>?
fun getTourMetaAsString(tour_id: String): Observable<String>?
fun getTourMetaAsString(tour_id: String): Observable<String>
fun getTourFiles(tour_id: String, resolution: String): Observable<List<TourFilesDataRaw>>
fun getAppVersion(): Observable<AppVersionRaw>
fun getToursPreviewById(tourIds: List<String>): Observable<List<TourPreviewRaw>>
......
......@@ -68,6 +68,12 @@ class FileModule @Inject constructor(val context: Application) {
// fun deleteFile(uri:String)= getFile(uri).delete()
fun deleteAssetFile(uri:String) =
getAssetFile(uri).delete()
fun getAssetFile(uri:String) =
File(assetsDirectory(context).plus(uri))
fun deleteAllCacheObservable() =
Observable.create<Pair<Int, Int>> {emitter ->
val foldersToDelete = listOf(
......
package com.biganto.visual.roompark.data.service.download
import com.biganto.visual.roompark.data.repository.db.requrey.RevisionString
import com.biganto.visual.roompark.data.repository.db.requrey.model.FileEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.TourFileJunctionEntity
import com.biganto.visual.roomparkvr.data.repository.db.requery.model.DownloadState
/**
* Created by Vladislav Bogdashkin on 14.04.2020.
*/
data class TourFileData(
val fileUrl: RevisionString,
val tourId: String,
var tempDownloadedSize: Long = 0L,
var tempOverallFileSize: Long = 0L,
var fileDownloadedSize: Long = 0L,
var tempTourTotalDiff: Long = 0L,
var isDownloaded: Boolean = false,
val fatalState: DownloadState? = null
) {
constructor(entity: FileEntity, junction: TourFileJunctionEntity) : this(
fileUrl = junction.file
, tourId = junction.tour
, tempDownloadedSize = 0L
, tempOverallFileSize = entity.totalSize
, fileDownloadedSize = entity.downloadedSize
, tempTourTotalDiff = 0L
, isDownloaded = entity.isDownloaded
)
}
package com.biganto.visual.roompark.data.service.lifecycle
/**
* Created by Vladislav Bogdashkin on 14.04.2020.
*/
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import timber.log.Timber
import javax.inject.Singleton
@Singleton
class AppLifecycleListener : LifecycleObserver {
private var isForeground=false
val IsAppForeground : Boolean
get() = isForeground
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onMoveToForeground() {
Timber.d("Returning to foreground…")
isForeground=true
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onMoveToBackground() {
Timber.d("Moving to background…")
isForeground=false
}
}
......@@ -39,9 +39,9 @@ const val PENDING_REQUEST_CODE=0
class NotificationCenter @Inject constructor(val context: Context) {
private val updateProgressNotificationDelay_Milliseconds= 333
var lastTimeProgressNotificationUpdated = 0L
private var lastTimeProgressNotificationUpdated = 0L
val actualNotifyManager:NotificationManager
private val actualNotifyManager:NotificationManager
get()= context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
init {
......
......@@ -10,6 +10,8 @@ import com.biganto.visual.roompark.data.repository.api.room_park.IRoomParkApi
import com.biganto.visual.roompark.data.repository.db.IDb
import com.biganto.visual.roompark.data.repository.db.requrey.DbModule
import com.biganto.visual.roompark.data.repository.file.FileModule
import com.biganto.visual.roompark.data.service.lifecycle.AppLifecycleListener
import com.biganto.visual.roompark.data.service.notification.NotificationCenter
import com.biganto.visual.roompark.domain.contract.*
import dagger.BindsInstance
import dagger.Component
......@@ -64,6 +66,11 @@ interface AppComponent : AndroidInjector<RoomParkApplication>{
fun provideTour():TourContract
fun provideLifeCycle(): AppLifecycleListener
fun provideNotifivations():NotificationCenter
fun provideAppContext():Application
fun provideFileSystem(): FileModule
......
......@@ -10,6 +10,8 @@ import com.biganto.visual.roompark.data.repository.api.room_park.RetrofitReposit
import com.biganto.visual.roompark.data.repository.db.IDb
import com.biganto.visual.roompark.data.repository.db.requrey.DbModule
import com.biganto.visual.roompark.data.repository.db.requrey.RequeryRepository
import com.biganto.visual.roompark.data.service.lifecycle.AppLifecycleListener
import com.biganto.visual.roompark.data.service.notification.NotificationCenter
import com.biganto.visual.roompark.domain.contract.*
import dagger.Binds
import dagger.Component
......@@ -71,6 +73,14 @@ abstract class DataModule {
@Binds
abstract fun provideRoomParkApi(roomParkApi:RetrofitRepository): IRoomParkApi
@Singleton
@Binds
abstract fun provideLifecycleObserver(obs:AppLifecycleListener): AppLifecycleListener
@Singleton
@Binds
abstract fun provideNotyCenter(center:NotificationCenter): NotificationCenter
@Singleton
@Binds
abstract fun provideDb(db: RequeryRepository) : IDb
......
......@@ -10,6 +10,7 @@ import com.biganto.visual.roompark.data.repository.db.requrey.model.FileEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.TourFileJunctionEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.fromRaw
import com.biganto.visual.roompark.data.repository.file.FileModule
import com.biganto.visual.roompark.data.service.download.TourFileData
import com.biganto.visual.roomparkvr.data.repository.db.requery.model.DownloadState
import com.biganto.visual.roomparkvr.data.repository.db.requery.model.TourPreviewEntity
import io.reactivex.BackpressureStrategy
......@@ -142,7 +143,8 @@ class DownloadUseCase @Inject constructor(
}
private fun observableTourDownloading(tour: TourPreviewEntity, token: CancellationToken) =
private fun observableTourDownloading(tour: TourPreviewEntity, token: CancellationToken)
: Observable<TourPreviewEntity> =
api.getTourFiles(tour.id, tour.targetResolution.toString())
.map { tourDbModel = tour;it.first() }
.map { raw ->
......@@ -172,30 +174,18 @@ class DownloadUseCase @Inject constructor(
junctionList
}
.doOnNext { junctionList ->
db.upsertTourFileJunction(junctionList)?.subscribe { Timber.d("junction upserted") }
}
.doOnNext { _ ->
.flatMap{ list ->
tourDbModel?.let {
db.upsertTourPreview(it)?.subscribe { Timber.d("tour upserted") }
Observable.merge(
db.upsertTourPreview(it).map { list }, db.upsertTourFileJunction(list)
)
}
}
.flatMapIterable { it }
.flatMap { junction ->
db.getFileEntity(junction.file)
.observable()
.map { entity ->
TourFileData(
fileUrl = junction.file
, tourId = junction.tour
, tempDownloadedSize = 0L
, tempOverallFileSize = entity.totalSize
, fileDownloadedSize = entity.downloadedSize
, tempTourTotalDiff = 0L
, isDownloaded = entity.isDownloaded
)
}
.map { entity -> TourFileData(entity,junction) }
}
.toFlowable(BackpressureStrategy.BUFFER)
.parallel(4)
......@@ -205,41 +195,32 @@ class DownloadUseCase @Inject constructor(
if (model.isDownloaded)
return@flatMap Flowable.just(model)
var header: HashMap<String, String>? = null
if (model.fileDownloadedSize > 0){
header = hashMapOf(Pair("Range", "bytes=${model.fileDownloadedSize}-"))
Timber.w("trying to continue download file " +
"url by: ${model.fileUrl}" +
"size is: ${model.fileDownloadedSize}/${model.tempOverallFileSize}" +
"and header is: $header")
}
val header: HashMap<String, String>? =
if (model.fileDownloadedSize > 0)
hashMapOf(Pair("Range", "bytes=${model.fileDownloadedSize}-"))
else null
api.downloadFile(model.fileUrl.revisionUri(), header)
.doOnError {
Timber.e(it)
}
.flatMap<TourFileData> {
writeFile(it, model, token)
.toFlowable(BackpressureStrategy.BUFFER)
.doOnCancel { Timber.d("CANCELLED") }
.doOnCancel { Timber.w("TOUR DOWNLOADING CANCELLED") }
}
.flatMap { downloadInfo ->
db.upsertFileEntity(
FileEntity().also{
it.setUri(downloadInfo.fileUrl)
it.setDownloadedSize(downloadInfo.fileDownloadedSize)
it.setTotalSize(downloadInfo.tempOverallFileSize)
it.setDownloaded(downloadInfo.isDownloaded)})
FileEntity().apply {
setUri(downloadInfo.fileUrl)
setDownloadedSize(downloadInfo.fileDownloadedSize)
setTotalSize(downloadInfo.tempOverallFileSize)
setDownloaded(downloadInfo.isDownloaded)
}
)
.toFlowable(BackpressureStrategy.BUFFER)
.map { downloadInfo }
}
}
.sequential()
.toObservable()
// .buffer(15L,TimeUnit.MILLISECONDS)
// .flatMapIterable { it }
.map { model ->
setDownloadInfo(
model.tourId
......@@ -250,8 +231,7 @@ class DownloadUseCase @Inject constructor(
model.tempDownloadedSize = 0
model.tourId
}
.delay(14L, TimeUnit.MILLISECONDS)
// .sample(37L, TimeUnit.MILLISECONDS)
.delay(12L, TimeUnit.MILLISECONDS)
.flatMap { db.upsertTourPreview(tourDbModel!!) }
......@@ -273,27 +253,25 @@ class DownloadUseCase @Inject constructor(
private fun getMeta(tour: TourPreviewEntity) =
api.getTourMetaAsString(tour.id)
?.doOnNext { meta ->
tour.let {
val metaUri = RevisionString("$META_PREDICTION${tour.id}$META_FILE_TYPE")
it.setMetaFileEntityId(metaUri)
.map { meta ->
tour.apply {
val metaUri =
RevisionString("$META_PREDICTION${tour.id}$META_FILE_TYPE")
setMetaFileEntityId(metaUri)
fileModule.saveFileToDisk(
File(
FileModule.assetsDirectory(context).plus(metaUri.uri())
),meta
File(FileModule.assetsDirectory(context).plus(metaUri.uri()))
, meta
)
}
}
?.map { tour }
?.onErrorReturn {
.onErrorReturn {
tour.isDownloaded = DownloadState.Crushed
db.upsertTourPreview(tour)?.blockingSubscribe()
db.upsertTourPreview(tour).blockingSubscribe()
tour
}
//#endregion oldMethod
private fun refreshGallery(file: File) {
MediaScannerConnection.scanFile(
context, arrayOf(file.path), null
......@@ -303,15 +281,5 @@ class DownloadUseCase @Inject constructor(
}
}
data class TourFileData(
val fileUrl: RevisionString,
val tourId: String,
var tempDownloadedSize: Long = 0L,
var tempOverallFileSize: Long = 0L,
var fileDownloadedSize: Long = 0L,
var tempTourTotalDiff: Long = 0L,
var isDownloaded: Boolean = false
)
data class CancellationToken(var isCancelled: Boolean)
}
\ No newline at end of file
......@@ -112,6 +112,14 @@
<!--endregion-->
<string name="on_all_tours_downloaded_notification_message">Загрузка туров завершена</string>
<string name="on_all_tours_deleted_notification_message">Удаление туров завершено</string>
<string name="noty_tours_delete_left">Осталось удалить: %d%n</string>
<string name="noty_tours_download_left">Осталось загрузить: %d%n</string>
<string name="game_view_content_description" />
</resources>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment