Skip to content

Commit aa740a9

Browse files
In app file uploading status implemented
in app file upload status implemented
1 parent 631efd7 commit aa740a9

33 files changed

+855
-179
lines changed

app/src/main/java/com/github/code/gambit/backgroundtask/FileUploadWorker.kt

Lines changed: 83 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@ import android.app.PendingIntent
66
import android.content.Context
77
import android.content.Intent
88
import android.os.Build
9+
import androidx.annotation.RequiresApi
910
import androidx.core.app.NotificationCompat
10-
import androidx.core.app.NotificationManagerCompat
1111
import androidx.room.Room
1212
import androidx.work.CoroutineWorker
13+
import androidx.work.ForegroundInfo
14+
import androidx.work.WorkManager
1315
import androidx.work.WorkerParameters
1416
import androidx.work.workDataOf
1517
import com.github.code.gambit.R
1618
import com.github.code.gambit.data.entity.chache.FileCacheEntity
19+
import com.github.code.gambit.data.entity.chache.FileMetaDataCacheEntity
1720
import com.github.code.gambit.data.entity.network.FileNetworkEntity
1821
import com.github.code.gambit.data.local.Database
19-
import com.github.code.gambit.data.local.FileDao
2022
import com.github.code.gambit.data.mapper.cache.FileCacheMapper
2123
import com.github.code.gambit.data.mapper.network.FileNetworkMapper
2224
import com.github.code.gambit.data.model.FileMetaData
@@ -33,10 +35,21 @@ import retrofit2.Retrofit
3335
import retrofit2.converter.gson.GsonConverterFactory
3436
import timber.log.Timber
3537
import java.io.File
38+
import java.lang.Exception
39+
import java.util.Calendar
3640
import kotlin.math.pow
3741

3842
class FileUploadWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) {
3943

44+
private val _db =
45+
Room.databaseBuilder(applicationContext, Database::class.java, AppConstant.Database.DB_NAME)
46+
.fallbackToDestructiveMigration()
47+
.build()
48+
private val db get() = _db
49+
50+
private val fileDao get() = db.fileDao()
51+
private val fileMetaDataDao get() = db.fileMetaDataDao()
52+
4053
/**
4154
* @inputData filePath: String is the absolute file path
4255
* @inputData fileName: String name of the file
@@ -49,20 +62,50 @@ class FileUploadWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker
4962
val fmd = FileMetaData.fromString(fileMetaDataString)
5063
val uid = System.currentTimeMillis().toInt()
5164
val size = String.format("%.2f", fmd.size.div(10.0.pow(6.0)))
52-
makeStatusNotification(uid, "New file", "Uploading file ${fmd.name} of size $size MB", true)
65+
try {
66+
val data = FileMetaDataCacheEntity(
67+
id.toString(),
68+
Calendar.getInstance().timeInMillis,
69+
fmd.path,
70+
fmd.name,
71+
fmd.size
72+
)
73+
fileMetaDataDao.insertFileMetaData(data)
74+
Timber.tag("worker").i("added file in db")
75+
} catch (err: Exception) {
76+
Timber.tag("worker").i(err.localizedMessage)
77+
}
78+
setForeground(
79+
makeStatusNotification(
80+
uid,
81+
"New file",
82+
"Uploading file ${fmd.name} of size $size MB"
83+
)
84+
)
85+
/*val test = true
86+
if (test) {
87+
delay(60000)
88+
return Result.success(
89+
workDataOf(
90+
AppConstant.Worker.FILE_OUTPUT_KEY to
91+
FileNetworkEntity("", "", "test-hash", fmd.name, fmd.size, ".any").toString()
92+
)
93+
)
94+
}*/
5395
val file = File(fmd.path)
54-
val a = System.currentTimeMillis()
5596
val res = InfuraIPFS().add.file(file, fmd.name, fmd.name).Hash
56-
val b = System.currentTimeMillis()
57-
// val res = "test-hash-to-avoid-unnecessary-server-call"
58-
Timber.tag("out").i(res)
59-
Timber.tag("out").i("Took ${b - a} ms")
60-
val fileDao = getFileDao()
97+
val fileDao = fileDao
6198
val fileService = getFileService()
62-
val task = fileService.uploadFile(FileNetworkEntity("", "", res, fmd.name, fmd.size, fmd.name.split(".")[1]))
99+
val fne = FileNetworkEntity("", "", res, fmd.name, fmd.size, fmd.name.split(".")[1])
100+
val task = fileService.uploadFile(fne)
63101
fileDao.insertFiles(getFileCacheEntityFromFileNetworkEntity(task))
64102
val data = workDataOf(AppConstant.Worker.FILE_OUTPUT_KEY to task.toString())
65-
makeStatusNotification(uid, "File Uploaded", task.toString(), false)
103+
try {
104+
fileMetaDataDao.deleteFileMetaData(id.toString())
105+
Timber.tag("worker").i("deleted file from db")
106+
} catch (err: Exception) {
107+
Timber.tag("worker").i(err.localizedMessage)
108+
}
66109
return Result.success(data)
67110
}
68111

@@ -72,12 +115,6 @@ class FileUploadWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker
72115
return cacheMapper.mapToEntity(networkMapper.mapFromEntity(fileNetworkEntity))
73116
}
74117

75-
private fun getFileDao(): FileDao {
76-
return Room.databaseBuilder(applicationContext, Database::class.java, AppConstant.Database.DB_NAME)
77-
.fallbackToDestructiveMigration()
78-
.build().fileDao()
79-
}
80-
81118
private fun getApiService(): ApiService {
82119
return Retrofit.Builder().baseUrl(AppConstant.BASE_URL)
83120
.addConverterFactory(
@@ -90,55 +127,64 @@ class FileUploadWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker
90127
}
91128

92129
private fun getFileService(): FileService {
93-
return FileServiceImpl(getApiService(), UserManager(applicationContext), LastEvaluatedKeyManager(applicationContext))
130+
return FileServiceImpl(
131+
getApiService(),
132+
UserManager(applicationContext),
133+
LastEvaluatedKeyManager(applicationContext)
134+
)
94135
}
95136

96137
/**
97138
* @param id Notification id
98139
* @param title notification title
99140
* @param message Notification message
100-
* @param progress determines whether to show progress or not
101141
*/
102-
private fun makeStatusNotification(id: Int, title: String, message: String, progress: Boolean) {
142+
private fun makeStatusNotification(id: Int, title: String, message: String): ForegroundInfo {
103143
val context = applicationContext
104144
// Make a channel if necessary
105145
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
106146
// Create the NotificationChannel, but only on API 26+ because
107147
// the NotificationChannel class is new and not in the support library
108-
val name = AppConstant.Notification.CHANNEL_NAME
109-
val description = AppConstant.Notification.CHANNEL_DESCRIPTION
110-
val importance = NotificationManager.IMPORTANCE_HIGH
111-
val channel = NotificationChannel(AppConstant.Notification.CHANNEL_ID, name, importance)
112-
channel.description = description
113-
114-
// Add the channel
115-
val notificationManager =
116-
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
117-
118-
notificationManager?.createNotificationChannel(channel)
148+
createChannel()
119149
}
120150

121151
val intent = Intent(context, MainActivity::class.java).apply {
122152
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
123153
}
124154

125155
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
126-
156+
val cancelIntent =
157+
WorkManager.getInstance(applicationContext).createCancelPendingIntent(getId())
127158
// Create the notification
128159
val builder = NotificationCompat.Builder(context, AppConstant.Notification.CHANNEL_ID)
129160
.setSmallIcon(R.drawable.ic_launcher_foreground)
130161
.setContentTitle(title)
131162
.setContentText(message)
132163
.setContentIntent(pendingIntent)
164+
.setProgress(0, 0, true)
165+
.setOngoing(true)
166+
.addAction(android.R.drawable.ic_delete, "Cancel Upload", cancelIntent)
133167
.setPriority(NotificationCompat.PRIORITY_HIGH)
134168
.setStyle(NotificationCompat.BigTextStyle().bigText(message))
135169
.setVibrate(LongArray(0))
136170

137-
if (progress) {
138-
builder.setProgress(0, 0, true)
139-
}
171+
// NotificationManagerCompat.from(applicationContext).notify(1, builder.build())
172+
173+
return ForegroundInfo(id, builder.build())
174+
}
175+
176+
@RequiresApi(Build.VERSION_CODES.O)
177+
fun createChannel() {
178+
val name = AppConstant.Notification.CHANNEL_NAME
179+
val description = AppConstant.Notification.CHANNEL_DESCRIPTION
180+
val importance = NotificationManager.IMPORTANCE_HIGH
181+
val channel = NotificationChannel(AppConstant.Notification.CHANNEL_ID, name, importance)
182+
channel.description = description
183+
184+
// Add the channel
185+
val notificationManager =
186+
applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
140187

141-
// Show the notification
142-
NotificationManagerCompat.from(context).notify(id, builder.build())
188+
notificationManager?.createNotificationChannel(channel)
143189
}
144190
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.github.code.gambit.data.entity.chache
2+
3+
import androidx.room.ColumnInfo
4+
import androidx.room.Entity
5+
import androidx.room.PrimaryKey
6+
7+
@Entity(tableName = "fileMetaData")
8+
class FileMetaDataCacheEntity(
9+
10+
@PrimaryKey(autoGenerate = false)
11+
@ColumnInfo(name = "uuid")
12+
val uuid: String,
13+
14+
@ColumnInfo(name = "timestamp")
15+
var timestamp: Long,
16+
17+
@ColumnInfo(name = "path")
18+
val path: String,
19+
20+
@ColumnInfo(name = "name")
21+
val name: String,
22+
23+
@ColumnInfo(name = "size")
24+
val size: Int
25+
26+
)

app/src/main/java/com/github/code/gambit/data/local/CacheDataSource.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.code.gambit.data.local
22

33
import com.github.code.gambit.data.model.File
4+
import com.github.code.gambit.data.model.FileMetaData
45
import com.github.code.gambit.data.model.Url
56

67
interface CacheDataSource {
@@ -9,4 +10,9 @@ interface CacheDataSource {
910
suspend fun getFiles(): List<File>
1011
suspend fun insertUrls(urls: List<Url>): Long
1112
suspend fun getUrls(fileId: String): List<Url>
13+
suspend fun insertFileMetaData(fileMetaData: FileMetaData, uuid: String)
14+
suspend fun getFileMetaData(uuid: String): FileMetaData
15+
suspend fun getAllFileMetaData(): List<FileMetaData>
16+
suspend fun deleteFileMetaData(uuid: String)
17+
suspend fun clearAllFileMetaData()
1218
}

app/src/main/java/com/github/code/gambit/data/local/CacheDataSourceImpl.kt

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
package com.github.code.gambit.data.local
22

3+
import com.github.code.gambit.data.entity.chache.FileMetaDataCacheEntity
34
import com.github.code.gambit.data.mapper.cache.FileCacheMapper
5+
import com.github.code.gambit.data.mapper.cache.FileMetaDataMapper
46
import com.github.code.gambit.data.mapper.cache.UrlCacheMapper
57
import com.github.code.gambit.data.model.File
8+
import com.github.code.gambit.data.model.FileMetaData
69
import com.github.code.gambit.data.model.Url
10+
import java.util.Calendar
711

812
class CacheDataSourceImpl
913
constructor(
10-
val fileCacheMapper: FileCacheMapper,
11-
val urlCacheMapper: UrlCacheMapper,
12-
val fileDao: FileDao,
13-
val urlDao: UrlDao
14+
private val fileCacheMapper: FileCacheMapper,
15+
private val urlCacheMapper: UrlCacheMapper,
16+
private val fileMetaDataMapper: FileMetaDataMapper,
17+
private val fileDao: FileDao,
18+
private val urlDao: UrlDao,
19+
private val fileWorkerDao: FileMetaDataDao
1420
) : CacheDataSource {
1521

1622
override suspend fun getFiles(): List<File> {
@@ -35,4 +41,27 @@ constructor(
3541
val urls = urlDao.getUrls(fileId)
3642
return urlCacheMapper.mapFromEntityList(urls)
3743
}
44+
45+
override suspend fun insertFileMetaData(fileMetaData: FileMetaData, uuid: String) {
46+
val data: FileMetaDataCacheEntity = fileMetaDataMapper.mapToEntity(fileMetaData)
47+
data.timestamp = Calendar.getInstance().timeInMillis
48+
return fileWorkerDao.insertFileMetaData(data)
49+
}
50+
51+
override suspend fun getFileMetaData(uuid: String): FileMetaData {
52+
val res = fileWorkerDao.getFileMetaData(uuid)[0]
53+
return FileMetaData(res.path, res.name, res.size)
54+
}
55+
56+
override suspend fun getAllFileMetaData(): List<FileMetaData> {
57+
return fileMetaDataMapper.mapFromEntityList(fileWorkerDao.getAllFileMetaData())
58+
}
59+
60+
override suspend fun deleteFileMetaData(uuid: String) {
61+
return fileWorkerDao.deleteFileMetaData(uuid)
62+
}
63+
64+
override suspend fun clearAllFileMetaData() {
65+
return fileWorkerDao.deleteAll()
66+
}
3867
}

app/src/main/java/com/github/code/gambit/data/local/Database.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ package com.github.code.gambit.data.local
33
import androidx.room.Database
44
import androidx.room.RoomDatabase
55
import com.github.code.gambit.data.entity.chache.FileCacheEntity
6+
import com.github.code.gambit.data.entity.chache.FileMetaDataCacheEntity
67
import com.github.code.gambit.data.entity.chache.UrlCacheEntity
78

8-
@Database(entities = [FileCacheEntity::class, UrlCacheEntity::class], version = 1)
9+
@Database(entities = [FileCacheEntity::class, UrlCacheEntity::class, FileMetaDataCacheEntity::class], version = 2)
910
abstract class Database : RoomDatabase() {
1011

1112
abstract fun fileDao(): FileDao
1213
abstract fun urlDao(): UrlDao
14+
abstract fun fileMetaDataDao(): FileMetaDataDao
1315
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.github.code.gambit.data.local
2+
3+
import androidx.room.Dao
4+
import androidx.room.Insert
5+
import androidx.room.OnConflictStrategy
6+
import androidx.room.Query
7+
import com.github.code.gambit.data.entity.chache.FileMetaDataCacheEntity
8+
9+
@Dao
10+
interface FileMetaDataDao {
11+
12+
@Insert(onConflict = OnConflictStrategy.REPLACE)
13+
suspend fun insertFileMetaData(fileMetaDataCacheEntity: FileMetaDataCacheEntity)
14+
15+
@Query("SELECT * FROM fileMetaData WHERE uuid = :uuid")
16+
suspend fun getFileMetaData(uuid: String): List<FileMetaDataCacheEntity>
17+
18+
@Query("SELECT * FROM fileMetaData ORDER BY timestamp DESC")
19+
suspend fun getAllFileMetaData(): List<FileMetaDataCacheEntity>
20+
21+
@Query("DELETE FROM fileMetaData WHERE uuid = :uuid")
22+
suspend fun deleteFileMetaData(uuid: String)
23+
24+
@Query("DELETE FROM fileMetaData")
25+
suspend fun deleteAll()
26+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.github.code.gambit.data.mapper.cache
2+
3+
import com.github.code.gambit.data.EntityMapper
4+
import com.github.code.gambit.data.entity.chache.FileMetaDataCacheEntity
5+
import com.github.code.gambit.data.model.FileMetaData
6+
import javax.inject.Inject
7+
8+
class FileMetaDataMapper
9+
@Inject
10+
constructor() : EntityMapper<FileMetaDataCacheEntity, FileMetaData> {
11+
12+
override fun mapFromEntity(entity: FileMetaDataCacheEntity): FileMetaData {
13+
return FileMetaData(entity.path, entity.name, entity.size, entity.uuid)
14+
}
15+
16+
override fun mapToEntity(domainModel: FileMetaData): FileMetaDataCacheEntity {
17+
val uuid = domainModel.uuid?.let { domainModel.uuid } ?: ""
18+
return FileMetaDataCacheEntity(
19+
uuid,
20+
0L,
21+
domainModel.path,
22+
domainModel.name,
23+
domainModel.size
24+
)
25+
}
26+
27+
override fun mapFromEntityList(entities: List<FileMetaDataCacheEntity>): List<FileMetaData> {
28+
return entities.map { mapFromEntity(it) }
29+
}
30+
31+
fun mapToEntityList(entities: List<FileMetaData>): List<FileMetaDataCacheEntity> {
32+
return entities.map { mapToEntity(it) }
33+
}
34+
}

0 commit comments

Comments
 (0)