Skip to content

Instantly share code, notes, and snippets.

@sajjadyousefnia
Created June 20, 2024 16:12
Show Gist options
  • Save sajjadyousefnia/22b9ac7fb0318306ab16d5401d5693d3 to your computer and use it in GitHub Desktop.
Save sajjadyousefnia/22b9ac7fb0318306ab16d5401d5693d3 to your computer and use it in GitHub Desktop.
package com.sands.android.view.activity
import android.Manifest
import android.annotation.SuppressLint
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.pm.PackageManager
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Bundle
import kotlinx.coroutines.*
import android.os.Environment
import android.os.Message
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.getSystemService
import androidx.core.net.toUri
import androidx.recyclerview.widget.LinearLayoutManager
import com.sands.android.App.Companion.DOWNLOADS_SUB_DIRECTORY
import com.sands.android.App.Companion.RUNNING_CHECK_TIME
import com.sands.android.App.Companion.db
import com.sands.android.App.Companion.getDownloadedFileDirectory
import com.sands.android.BroadcastReceiver.DownloadReceiver
import com.sands.android.Service.DownloadService
import com.sands.android.dao.entity.DownloadModel
import com.sands.android.databinding.ActivityDownloadBinding
import com.sands.android.view.adapter.AdapterHistoryDownload
import com.sands.android.view.adapter.AdapterRunningDownload
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Calendar
import java.math.BigDecimal
import java.math.RoundingMode
class DownloadActivity : AppCompatActivity() {
// private var currentTitle: String = ""
// private var currentUrl: String = ""
private var periodicJob: Job? = null
private var service: DownloadService? = null
private var bound: Boolean = false
private val TAG = "DownloadActivity"
private lateinit var runningAdapter: AdapterRunningDownload
private lateinit var historyAdapter: AdapterHistoryDownload
private lateinit var downloadCompletedReceiver: BroadcastReceiver
private var isCursorOpen = true
private var runningDownloadList = mutableListOf<DownloadModel>()
private var historyDownloadList = mutableListOf<DownloadModel>()
private val downloadScope = CoroutineScope(Dispatchers.IO)
private val secondDownloadScope = CoroutineScope(Dispatchers.IO)
private val checkScope = CoroutineScope(Dispatchers.IO)
private var lastTime = System.currentTimeMillis()
private var lastDownloadedBytes: Long = 0
/*
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
val binder = service as DownloadService.LocalBinder
this@DownloadActivity.service = binder.getService()
this@DownloadActivity.service!!.updateServiceFromActivity(object :
OnServiceChangeListener {
override fun onDownloadStarted(id: Int) {
}
override fun onDownloadFailed(id: Int, error: String) {
}
override fun onDownloadProgress(id: Int, progress: Int) {
}
override fun onDownloadCompleted(id: Int) {
}
})
bound = true
}
override fun onServiceDisconnected(arg0: ComponentName) {
bound = false
}
}
*/
private lateinit var binding: ActivityDownloadBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
binding = ActivityDownloadBinding.inflate(layoutInflater)
setContentView(binding.root)
downloadCompletedReceiver = DownloadReceiver()
setupAdapters()
if (checkIfHasDownload()) {
downloadScope.launch {
downloadUsingSystemService()
}
startCheckRunningDownloadsInPeriod()
}
checkScope.launch {
checkDownloadsHistory()
}
secondDownloadScope.launch {
checkRunningDownloads()
}
}
@SuppressLint("Range")
private fun startCheckRunningDownloadsInPeriod() {
periodicJob = CoroutineScope(Dispatchers.IO).launch {
while (isActive) { // Check if the coroutine is still active
// Your periodic work
runningDownloadList.forEach {
if (it.isComplete == false) {
val downloadId = it.downloadId
val query = DownloadManager.Query().setFilterById(downloadId)
val downloadManager =
getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val cursor = downloadManager.query(query)
if (cursor != null && cursor.moveToFirst() == false && it.isStopped == false && isCursorOpen) {
it.isStopped = true
withContext(Dispatchers.Main) {
try {
runningAdapter.notifyDataSetChanged()
} catch (e: Exception) {
e.printStackTrace()
}
}
} else if (cursor != null && cursor.moveToFirst() == true && it.isStopped == true && isCursorOpen) {
it.isStopped = false
withContext(Dispatchers.Main) {
try {
runningAdapter.notifyDataSetChanged()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
cursor.close()
}
}
delay(RUNNING_CHECK_TIME) // Delay for milliseconds
}
}
}
private fun setupAdapters() {
runningAdapter = AdapterRunningDownload(this@DownloadActivity, runningDownloadList)
historyAdapter = AdapterHistoryDownload(this@DownloadActivity, historyDownloadList)
binding.rvRunningDownload.adapter = runningAdapter
binding.rvRunningDownload.layoutManager = LinearLayoutManager(this)
binding.rvHistoryDownload.adapter = historyAdapter
binding.rvHistoryDownload.layoutManager = LinearLayoutManager(this)
}
private suspend fun checkRunningDownloads() {
val allDownloads = db.appDao().getUnfinishedDownloadsHistory()
runningDownloadList.addAll(allDownloads)
withContext(Dispatchers.Main) {
historyAdapter.notifyDataSetChanged()
}
runningDownloadList.forEach { downloadModel ->
val downloadManager = getSystemService(DownloadManager::class.java)
observerDownload(
downloadId = downloadModel.id,
currentDownloadModel = downloadModel,
downloadManager = downloadManager
)
}
}
private suspend fun checkDownloadsHistory() {
val allDownloads = db.appDao().getCompleteDownloadsHistory()
historyDownloadList.addAll(allDownloads)
withContext(Dispatchers.Main) {
historyAdapter.notifyDataSetChanged()
}
}
/*
override fun onResume() {
super.onResume()
val intentFilter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(downloadCompletedReceiver, intentFilter, RECEIVER_EXPORTED)
} else {
registerReceiver(downloadCompletedReceiver, intentFilter)
}
}
*/
fun checkStoragePermissions(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
//Android is 11 (R) or above
return Environment.isExternalStorageManager()
} else {
//Below android 11
val write = ContextCompat.checkSelfPermission(
this, Manifest.permission.WRITE_EXTERNAL_STORAGE
)
val read = ContextCompat.checkSelfPermission(
this, Manifest.permission.READ_EXTERNAL_STORAGE
)
return read == PackageManager.PERMISSION_GRANTED && write == PackageManager.PERMISSION_GRANTED
}
}
/*
private fun requestForStoragePermissions() {
//Android is 11 (R) or above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
try {
val intent = Intent()
intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
val uri = Uri.fromParts("com.sands.android", this.packageName, null)
intent.setData(uri)
storageActivityResultLauncher.launch(intent)
} catch (e: Exception) {
val intent = Intent()
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
storageActivityResultLauncher.launch(intent)
}
} else {
//Below android 11
ActivityCompat.requestPermissions(
this, arrayOf<String>(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
), REQUEST_CODE_STORAGE_PERMISSION
)
}
}
*/
/*
private val storageActivityResultLauncher: ActivityResultLauncher<Intent> =
registerForActivityResult(ActivityResultContracts.StartActivityForResult(),
object : ActivityResultCallback<ActivityResult> {
override fun onActivityResult(result: ActivityResult) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
//Android is 11 (R) or above
if (Environment.isExternalStorageManager()) {
//Manage External Storage Permissions Granted
Log.d(
TAG, "onActivityResult: Manage External Storage Permissions Granted"
);
downloadScope.launch {
downloadUsingSystemService()
}
} else {
Toast.makeText(
this@DownloadActivity,
"Storage Permissions Denied",
Toast.LENGTH_SHORT
).show();
}
} else {
downloadScope.launch {
downloadUsingSystemService()
} //Below android 11
}
}
})
*/
/*
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<out String>, grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_CODE_STORAGE_PERMISSION) {
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
// Permission granted
downloadScope.launch {
downloadUsingSystemService()
}
} else {
// Permission denied
}
}
}
*/
private suspend fun checkDownloadExistsDB(): Boolean {
val downloadModel = runningDownloadList.last()
val isExist = db.appDao().checkDownloadExist(downloadModel.url)
return isExist != 0
}
private suspend fun downloadUsingSystemService() {
try {
val downloadModel = runningDownloadList.last()
if (downloadModel.isNew) {
doDownload(downloadModel)
} else {
// updateDownloadData(downloadModel)
// doDownload(downloadModel)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private suspend fun updateDownloadData(downloadModel: DownloadModel) {
val retainedDownloadModel = db.appDao().getDownloadByUrl(downloadModel.url)
downloadModel.downloadedBytes = retainedDownloadModel.downloadedBytes
downloadModel.percentage = retainedDownloadModel.percentage
downloadModel.currentSpeed = retainedDownloadModel.currentSpeed
downloadModel.remaingTime = retainedDownloadModel.remaingTime
downloadModel.isComplete = retainedDownloadModel.isComplete
downloadModel.startDateTime = retainedDownloadModel.startDateTime
}
private fun getCurrentDateTime(): String {
val currentTime: String = Calendar.getInstance().getTime().toString()
return currentTime
}
@SuppressLint("Range")
private suspend fun doDownload(currentDownloadModel: DownloadModel) {
try {
val downloadManager = getSystemService(DownloadManager::class.java)
val request = DownloadManager.Request(currentDownloadModel.url.toUri())
.setMimeType("video/${currentDownloadModel.url.substringAfterLast(".")}")
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI and DownloadManager.Request.NETWORK_MOBILE)
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
.setTitle("در حال دانلود فیلم " + currentDownloadModel.title)
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS,
getDownloadedFileDirectory(currentDownloadModel)
)
val downloadId = downloadManager.enqueue(request)
currentDownloadModel.downloadId = downloadId
val newId = db.appDao().insertNewDownload(currentDownloadModel)
currentDownloadModel.id = newId
observerDownload(downloadId, currentDownloadModel, downloadManager)
/* val query = DownloadManager.Query().setFilterById(downloadId)
var isDownloading = true
val newId = db.appDao().insertNewDownload(currentDownloadModel)
currentDownloadModel.id = newId
withContext(Dispatchers.Main) {
try {
runningAdapter.notifyDataSetChanged()
} catch (e: Exception) {
e.printStackTrace()
}
}
var lastBytesDownladed = 0L
while (isDownloading) {
isCursorOpen = false
val cursor = downloadManager.query(query)
if (cursor.moveToFirst()) {
val bytesDownloaded = cursor.getLong(
cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
)
val bytesTotal = cursor.getLong(
cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
)
if (lastBytesDownladed == bytesDownloaded || bytesDownloaded == 0L) {
continue
} else {
lastBytesDownladed = bytesDownloaded
}
// if (downloadModel.totalBytes == 0L) {
currentDownloadModel.totalBytes = bytesTotal
// }
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
if (status == DownloadManager.STATUS_SUCCESSFUL) {
isDownloading = false
} else if (status == DownloadManager.STATUS_FAILED) {
val reason =
cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON))
// listener?.onFailed("Download failed: $reason")
} else if (status == DownloadManager.STATUS_PAUSED) {
}
if (status == DownloadManager.STATUS_RUNNING) {
Log.d(
TAG,
"downloadFromScratch: download running bytes Downloaded:${bytesDownloaded} total bytes:${bytesTotal}"
)
currentDownloadModel.isStopped = false
// db.appDao().checkDownloadStopStatus(currentDownloadModel.id, false)
db.appDao().updateDownload(currentDownloadModel)
withContext(Dispatchers.Main) {
try {
runningAdapter.notifyDataSetChanged()
} catch (e: Exception) {
e.printStackTrace()
}
}
} else {
Log.d(TAG, "downloadFromScratch: download stopped")
if (currentDownloadModel.isStopped == false) {
currentDownloadModel.isStopped = true
// db.appDao().checkDownloadStopStatus(currentDownloadModel.id, true)
db.appDao().updateDownload(currentDownloadModel)
withContext(Dispatchers.Main) {
runningAdapter.notifyDataSetChanged()
}
}
}
if (bytesTotal > 0) {
val progress = (bytesDownloaded * 100L / bytesTotal).toInt()
currentDownloadModel.downloadId = downloadId
currentDownloadModel.downloadedBytes = bytesDownloaded
currentDownloadModel.percentage = progress
db.appDao().updateDownload(currentDownloadModel)
// db.appDao().updatePercentageDownload(downloadId, bytesDownloaded, progress)
val downloadItem = runningDownloadList.first()
downloadItem.downloadedBytes = bytesDownloaded.toLong()
downloadItem.percentage = progress
val speed = calculateDownloadSpeed(cursor)
if (speed != -1L && speed != 0L) {
downloadItem.currentSpeed = speed
downloadItem.remaingTime = guessRemainingTimeFinish(
bytesDownloaded, bytesTotal, speed.toLong()
)
}
if (bytesDownloaded == bytesTotal) {
doOnCompleteDownload(downloadItem)
}
// listener?.onProgress(progress)
}
}
cursor.close()
isCursorOpen = true}*/
} catch (e: Exception) {
e.printStackTrace()
}
}
@SuppressLint("Range")
private suspend fun observerDownload(
downloadId: Long, currentDownloadModel: DownloadModel, downloadManager: DownloadManager
) {
try {
val query = DownloadManager.Query().setFilterById(downloadId)
var isDownloading = true
withContext(Dispatchers.Main) {
try {
runningAdapter.notifyDataSetChanged()
} catch (e: Exception) {
e.printStackTrace()
}
}
// var lastBytesDownladed = 0L
while (isDownloading) {
isCursorOpen = false
val cursor = downloadManager.query(query)
if (cursor.moveToFirst()) {
val bytesDownloaded = cursor.getLong(
cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
)
val bytesTotal = cursor.getLong(
cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
)
if (currentDownloadModel.downloadedBytes == bytesDownloaded || bytesDownloaded == 0L) {
continue
} else {
currentDownloadModel.downloadedBytes = bytesDownloaded
}
// if (downloadModel.totalBytes == 0L) {
currentDownloadModel.totalBytes = bytesTotal
// }
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
if (status == DownloadManager.STATUS_SUCCESSFUL) {
isDownloading = false
} else if (status == DownloadManager.STATUS_FAILED) {
val reason =
cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON))
// listener?.onFailed("Download failed: $reason")
} else if (status == DownloadManager.STATUS_PAUSED) {
}
if (status == DownloadManager.STATUS_RUNNING) {
Log.d(
TAG,
"downloadFromScratch: download running bytes Downloaded:${bytesDownloaded} total bytes:${bytesTotal}"
)
currentDownloadModel.isStopped = false
// db.appDao().checkDownloadStopStatus(currentDownloadModel.id, false)
db.appDao().updateDownload(currentDownloadModel)
withContext(Dispatchers.Main) {
try {
runningAdapter.notifyDataSetChanged()
} catch (e: Exception) {
e.printStackTrace()
}
}
} else {
Log.d(TAG, "downloadFromScratch: download stopped")
if (currentDownloadModel.isStopped == false) {
currentDownloadModel.isStopped = true
// db.appDao().checkDownloadStopStatus(currentDownloadModel.id, true)
db.appDao().updateDownload(currentDownloadModel)
withContext(Dispatchers.Main) {
runningAdapter.notifyDataSetChanged()
}
}
}
if (bytesTotal > 0) {
val progress = (bytesDownloaded * 100L / bytesTotal).toInt()
currentDownloadModel.downloadId = downloadId
currentDownloadModel.downloadedBytes = bytesDownloaded
currentDownloadModel.percentage = progress
db.appDao().updateDownload(currentDownloadModel)
// db.appDao().updatePercentageDownload(downloadId, bytesDownloaded, progress)
val downloadItem = runningDownloadList.first()
downloadItem.downloadedBytes = bytesDownloaded.toLong()
downloadItem.percentage = progress
val speed = calculateDownloadSpeed(cursor)
if (speed != -1L && speed != 0L) {
downloadItem.currentSpeed = speed
downloadItem.remaingTime = guessRemainingTimeFinish(
bytesDownloaded, bytesTotal, speed.toLong()
)
}
if (bytesDownloaded == bytesTotal) {
doOnCompleteDownload(downloadItem)
}
// listener?.onProgress(progress)
}
}
cursor.close()
isCursorOpen = true
}
} catch (e: Exception) {
e.printStackTrace()
}
}
/*
@SuppressLint("Range")
private suspend fun continueExistingDownload() {
try {
val currentDownloadModel = runningDownloadList.last()
val retainedDownloadModel = db.appDao().getDownloadByUrl(currentDownloadModel.url)
updateDownloadModel(currentDownloadModel, retainedDownloadModel)
val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val query = DownloadManager.Query().setFilterById(currentDownloadModel.downloadId)
val cursor = downloadManager.query(query)
if (cursor != null && cursor.moveToFirst()) {
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
if (status == DownloadManager.STATUS_PAUSED) {
val url = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI))
val downloadedBytes =
cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
resumeDownload(url, downloadedBytes, currentDownloadModel)
}
cursor.close()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
*/
private suspend fun doOnCompleteDownload(downloadModel: DownloadModel) {
downloadModel.endDateTime = getCurrentDateTime()
downloadModel.isComplete = true
downloadModel.percentage = 100
downloadModel.isStopped = true
// db.appDao().updateFinishedDownload(downloadModel.id, downloadModel.endDateTime)
db.appDao().updateFinishedDownload(downloadModel.id, getCurrentDateTime())
withContext(Dispatchers.Main) {
historyDownloadList.add(downloadModel)
runningDownloadList.removeAll { it.id == downloadModel.id }
try {
runningAdapter.notifyDataSetChanged()
} catch (e: Exception) {
e.printStackTrace()
}
try {
historyAdapter.notifyDataSetChanged()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
/**
* return false means no video provided to download
* */
private fun checkIfHasDownload(): Boolean {
try {
val url = intent.extras!!.getString(
"url", ""
)
val title = intent.extras!!.getString("title", "")
val videoId = intent.extras!!.getLong("vid_id", 0L)
val isMovie = intent.extras!!.getBoolean("is_movie", true)
val cover = intent.extras!!.getString("cover", "")
val format = intent.extras!!.getString("format", "")
val isNew = intent.extras!!.getBoolean("is_new", true)
val year = intent.extras!!.getInt("year", 0)
val imdb = intent.extras!!.getString("imdb", "")
if (url != "" && title != "" && videoId != 0L && cover != "" && format != "" && isMovie) {
addDownloadDataToRunningList(
isMovie, url, title, videoId, cover, format, isNew, year, imdb
)
return true
} else {
return false
}
} catch (e: Exception) {
e.printStackTrace()
return false
}
}
private fun addDownloadDataToRunningList(
isMovie: Boolean,
url: String,
title: String,
videoId: Long,
cover: String,
format: String,
isNew: Boolean,
year: Int,
imdb: String
) {
val downloadModel = DownloadModel(
isMovie = isMovie,
videoId = videoId,
cover = cover,
url = url,
title = title,
downloadedBytes = 0,
downloadId = 0,
directory = Environment.DIRECTORY_DOWNLOADS + DOWNLOADS_SUB_DIRECTORY + title,
percentage = 0,
startDateTime = getCurrentDateTime(),
totalBytes = 0,
currentSpeed = 0L,
remaingTime = "",
fileName = title + getCurrentDateTime(),
isComplete = false,
format = format,
isNew = isNew,
year = year,
imdb = imdb
)
runningDownloadList.add(downloadModel)
}
// Method to send messages to the service
fun sendMessageToService(msg: String) {
if (bound) {
val message = Message.obtain(null, 0, 0, 0)
message.data = Bundle().apply {
putString("msg", msg)
}
service?.LocalBinder()?.getMessenger()?.send(message)
}
}
override fun onDestroy() {
super.onDestroy()
if (periodicJob != null && periodicJob?.isActive == true) {
periodicJob!!.cancel()
}
}
/*
override fun onDestroy() {
super.onDestroy()
unbindService(connection)
bound = false
}
*/
// Method to handle messages from the service
fun handleServiceMessage(msg: String?) {
// Update the UI or perform necessary actions based on the message
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
}
@SuppressLint("Range")
private suspend fun calculateDownloadSpeed(cursor: Cursor): Long {
// var speedInKbps = "_"
var speedInBytes = -1L
val downloadedBytes =
cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
if (downloadedBytes == 0L) {
Log.e(TAG, "calculateDownloadSpeed: downloadedBytes is zero")
return -1
}
val currentTime = System.currentTimeMillis()
val deltaTime = currentTime - lastTime
val deltaBytes = downloadedBytes - lastDownloadedBytes
if (deltaTime > 0) {
// val speed = (deltaBytes * 1000) / deltaTime // bytes per second
// speedInKbps = (speed / 1024).toString() // convert to Kbps
// speedInBites = (deltaBytes / deltaTime).toString()
speedInBytes = (BigDecimal(deltaBytes * 10).divide(
BigDecimal(deltaTime), 2, RoundingMode.HALF_EVEN
)).toLong()
}
lastTime = currentTime
lastDownloadedBytes = downloadedBytes
// return speedInKbps
return speedInBytes
}
/*
private fun notifyRunningItemChanged(downloadModel: DownloadModel) {
val index = runningDownloadList.indexOf(downloadModel)
if (index != -1) {
runningAdapter.notifyItemChanged(index)
}
}
*/
/*
private fun notifyRunningItemAdded(downloadModel: DownloadModel) {
val index = runningDownloadList.indexOf(downloadModel)
if (index != -1) {
runningAdapter.notifyItemInserted(index)
}
}
*/
/*
private fun notifyRunningItemRemoved(downloadModel: DownloadModel) {
val index = runningDownloadList.indexOf(downloadModel)
if (index != -1) {
runningAdapter.notifyItemRemoved(index)
}
}
*/
private fun guessRemainingTimeFinish(
bytesDownloaded: Long, bytesTotal: Long, speed: Long
): String {
var time = "_"
try {
val remainingBytes = bytesTotal - bytesDownloaded
val remainingTimeSeconds = (remainingBytes / speed)
val hours = remainingTimeSeconds.toInt() / 3600
val minutes = (remainingTimeSeconds.toInt() % 3600) / 60
val seconds = remainingTimeSeconds.toInt() % 60
if (hours > 0) {
time += "$hours ساعت "
}
if (minutes > 0) {
time += " $minutes دقیقه "
}
if (seconds > 0) {
time += " $seconds ثانیه "
}
time = time.replace("_", "")
} catch (e: Exception) {
e.printStackTrace()
}
return time
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment