Skip to content

Commit

Permalink
[feature|fix] Support for torrent seeding; fix player seek bug
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyD666 committed Feb 20, 2024
1 parent 9c726c5 commit c677eb0
Show file tree
Hide file tree
Showing 19 changed files with 549 additions and 54 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ android {
applicationId = "com.skyd.anivu"
minSdk = 24
targetSdk = 34
versionCode = 2
versionName = "1.0-beta04"
versionCode = 3
versionName = "1.0-beta05"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/skyd/anivu/config/Const.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ object Const {
val VIDEO_DIR = File(appContext.filesDir.path, "Video").apply {
if (!exists()) mkdirs()
}

val TORRENT_RESUME_DATA_DIR = File(appContext.filesDir.path, "TorrentResumeData").apply {
if (!exists()) mkdirs()
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/com/skyd/anivu/ext/ContextExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.ActivityNotFoundException
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.content.res.TypedArray
Expand Down Expand Up @@ -81,6 +82,17 @@ fun Context.getAppVersionName(): String {
return appVersionName
}

fun Context.getAppName(): String? {
return try {
val packageInfo: PackageInfo = packageManager.getPackageInfo(packageName, 0)
val labelRes: Int = packageInfo.applicationInfo.labelRes
getString(labelRes)
} catch (e: Exception) {
e.printStackTrace()
null
}
}

fun Context.openBrowser(url: String) {
try {
val uri: Uri = Uri.parse(url)
Expand Down
60 changes: 57 additions & 3 deletions app/src/main/java/com/skyd/anivu/model/bean/DownloadInfoBean.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package com.skyd.anivu.model.bean
import android.os.Parcelable
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Ignore
import androidx.room.Index
import com.skyd.anivu.base.BaseBean
import com.skyd.anivu.ui.adapter.variety.Diff
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable

Expand Down Expand Up @@ -43,11 +44,22 @@ data class DownloadInfoBean(
@ColumnInfo(name = DOWNLOAD_REQUEST_ID_COLUMN)
val downloadRequestId: String,
) : BaseBean, Parcelable, Diff {
@IgnoredOnParcel
@Ignore
var peerInfoList: List<PeerInfoBean> = emptyList()

@IgnoredOnParcel
@Ignore
var uploadPayloadRate: Int = 0

@IgnoredOnParcel
@Ignore
var downloadPayloadRate: Int = 0

enum class DownloadState {
Init, Downloading, Paused, Completed, ErrorPaused
Init, Downloading, Paused, Completed, ErrorPaused, StorageMovedFailed, Seeding, SeedingPaused
}


companion object {
const val LINK_COLUMN = "link"
const val NAME_COLUMN = "name"
Expand All @@ -61,6 +73,9 @@ data class DownloadInfoBean(

const val PAYLOAD_PROGRESS = "progress"
const val PAYLOAD_DESCRIPTION = "description"
const val PAYLOAD_PEER_INFO = "peerInfo"
const val PAYLOAD_UPLOAD_PAYLOAD_RATE = "uploadPayloadRate"
const val PAYLOAD_DOWNLOAD_PAYLOAD_RATE = "downloadPayloadRate"
const val PAYLOAD_DOWNLOAD_STATE = "downloadState"
const val PAYLOAD_NAME = "name"
const val PAYLOAD_DOWNLOADING_DIR_NAME = "downloadingDirName"
Expand All @@ -81,10 +96,49 @@ data class DownloadInfoBean(
val list: MutableList<Any> = mutableListOf()
if (progress != o.progress) list += PAYLOAD_PROGRESS
if (description != o.description) list += PAYLOAD_DESCRIPTION
if (peerInfoList != o.peerInfoList) list += PAYLOAD_PEER_INFO
if (uploadPayloadRate != o.uploadPayloadRate) list += PAYLOAD_UPLOAD_PAYLOAD_RATE
if (downloadPayloadRate != o.downloadPayloadRate) list += PAYLOAD_DOWNLOAD_PAYLOAD_RATE
if (downloadState != o.downloadState) list += PAYLOAD_DOWNLOAD_STATE
if (name != o.name) list += PAYLOAD_NAME
if (downloadingDirName != o.downloadingDirName) list += PAYLOAD_DOWNLOADING_DIR_NAME
if (size != o.size) list += PAYLOAD_SIZE
return list.ifEmpty { null }
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as DownloadInfoBean

if (link != other.link) return false
if (name != other.name) return false
if (downloadingDirName != other.downloadingDirName) return false
if (downloadDate != other.downloadDate) return false
if (size != other.size) return false
if (progress != other.progress) return false
if (description != other.description) return false
if (downloadState != other.downloadState) return false
if (downloadRequestId != other.downloadRequestId) return false
if (uploadPayloadRate != other.uploadPayloadRate) return false
if (downloadPayloadRate != other.downloadPayloadRate) return false
return peerInfoList == other.peerInfoList
}

override fun hashCode(): Int {
var result = link.hashCode()
result = 31 * result + name.hashCode()
result = 31 * result + downloadingDirName.hashCode()
result = 31 * result + downloadDate.hashCode()
result = 31 * result + size.hashCode()
result = 31 * result + progress.hashCode()
result = 31 * result + (description?.hashCode() ?: 0)
result = 31 * result + downloadState.hashCode()
result = 31 * result + downloadRequestId.hashCode()
result = 31 * result + peerInfoList.hashCode()
result = 31 * result + uploadPayloadRate.hashCode()
result = 31 * result + downloadPayloadRate.hashCode()
return result
}
}
41 changes: 41 additions & 0 deletions app/src/main/java/com/skyd/anivu/model/bean/PeerInfoBean.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.skyd.anivu.model.bean

import android.os.Parcelable
import com.skyd.anivu.base.BaseBean
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable
import org.libtorrent4j.PeerInfo.ConnectionType

@Parcelize
@Serializable
data class PeerInfoBean(
var client: String? = null,
var totalDownload: Long = 0,
var totalUpload: Long = 0,
var flags: Int = 0,
var source: Byte = 0,
var upSpeed: Int = 0,
var downSpeed: Int = 0,
var connectionType: ConnectionType? = null,
var progress: Float = 0f,
var progressPpm: Int = 0,
var ip: String? = null,
) : BaseBean, Parcelable {
companion object {
fun from(peerInfo: org.libtorrent4j.PeerInfo): PeerInfoBean {
return PeerInfoBean(
client = peerInfo.client(),
totalDownload = peerInfo.totalDownload(),
totalUpload = peerInfo.totalUpload(),
flags = peerInfo.flags(),
source = peerInfo.source(),
upSpeed = peerInfo.upSpeed(),
downSpeed = peerInfo.downSpeed(),
connectionType = peerInfo.connectionType(),
progress = peerInfo.progress(),
progressPpm = peerInfo.progressPpm(),
ip = peerInfo.ip()
)
}
}
}
3 changes: 1 addition & 2 deletions app/src/main/java/com/skyd/anivu/model/db/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.room.migration.Migration
import com.skyd.anivu.model.bean.ArticleBean
import com.skyd.anivu.model.bean.DownloadInfoBean
import com.skyd.anivu.model.bean.DownloadLinkUuidMapBean
Expand Down Expand Up @@ -47,7 +46,7 @@ abstract class AppDatabase : RoomDatabase() {
@Volatile
private var instance: AppDatabase? = null

private val migrations = arrayOf<Migration>(Migration1To2())
private val migrations = arrayOf(Migration1To2())

fun getInstance(context: Context): AppDatabase {
return if (instance == null) {
Expand Down
34 changes: 34 additions & 0 deletions app/src/main/java/com/skyd/anivu/model/db/dao/DownloadInfoDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,22 @@ interface DownloadInfoDao {
completedState: String = DownloadInfoBean.DownloadState.Completed.name
): Flow<List<DownloadInfoBean>>

@Transaction
@Query(
"""
SELECT * FROM $DOWNLOAD_INFO_TABLE_NAME
"""
)
fun getAllDownloadListFlow(): Flow<List<DownloadInfoBean>>

@Transaction
@Query(
"""
SELECT ${DownloadInfoBean.DOWNLOAD_REQUEST_ID_COLUMN} FROM $DOWNLOAD_INFO_TABLE_NAME
"""
)
fun getAllDownloadRequestIdFlow(): Flow<List<String>>

@Transaction
@Query("SELECT * FROM $DOWNLOAD_INFO_TABLE_NAME WHERE ${DownloadInfoBean.PROGRESS_COLUMN} < 1")
fun getDownloadingList(): List<DownloadInfoBean>
Expand All @@ -253,6 +269,15 @@ interface DownloadInfoDao {
)
fun getDownloadLinkByUuid(uuid: String): String?

@Transaction
@Query(
"""
SELECT ${DownloadLinkUuidMapBean.UUID_COLUMN} FROM $DOWNLOAD_LINK_UUID_MAP_TABLE_NAME
WHERE ${DownloadLinkUuidMapBean.LINK_COLUMN} == :link
"""
)
fun getDownloadUuidByLink(link: String): String?

@Transaction
@Query(
"""
Expand All @@ -261,4 +286,13 @@ interface DownloadInfoDao {
"""
)
fun removeDownloadLinkByUuid(uuid: String): Int

@Transaction
@Query(
"""
DELETE FROM $DOWNLOAD_LINK_UUID_MAP_TABLE_NAME
WHERE ${DownloadLinkUuidMapBean.LINK_COLUMN} == :link
"""
)
fun removeDownloadLinkByLink(link: String): Int
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import com.skyd.anivu.config.Const
import com.skyd.anivu.model.bean.DownloadInfoBean
import com.skyd.anivu.model.db.dao.DownloadInfoDao
import com.skyd.anivu.model.db.dao.SessionParamsDao
import com.skyd.anivu.model.worker.download.DownloadTorrentWorker
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import java.io.File
Expand All @@ -17,18 +20,40 @@ class DownloadRepository @Inject constructor(
private val sessionParamsDao: SessionParamsDao,
) : BaseRepository() {
fun requestDownloadingVideos(): Flow<List<DownloadInfoBean>> {
return downloadInfoDao.getDownloadingListFlow()
.flowOn(Dispatchers.IO)
return combine(
downloadInfoDao.getAllDownloadListFlow().distinctUntilChanged(),
DownloadTorrentWorker.peerInfoMapFlow,
DownloadTorrentWorker.torrentStatusMapFlow,
) { list, peerInfoMap, uploadPayloadRateMap ->
list.map { downloadInfoBean ->
downloadInfoBean.copy().apply {
peerInfoList = peerInfoMap.getOrDefault(downloadRequestId, emptyList()).toList()
val torrentStatus = uploadPayloadRateMap.get(downloadRequestId)
if (torrentStatus != null) {
uploadPayloadRate = torrentStatus.uploadPayloadRate()
downloadPayloadRate = torrentStatus.downloadPayloadRate()
}
}
}
}.flowOn(Dispatchers.IO)
}

suspend fun deleteDownloadTaskInfo(
link: String,
downloadingDirName: String,
): Flow<Unit> {
return flow {
if (downloadingDirName.isNotBlank()) {
File(Const.DOWNLOADING_VIDEO_DIR, downloadingDirName).deleteRecursively()
}
val requestUuid = downloadInfoDao.getDownloadInfo(link)?.downloadRequestId
if (!requestUuid.isNullOrBlank()) {
File(Const.TORRENT_RESUME_DATA_DIR, requestUuid).deleteRecursively()
}
// 这些最后删除,防止上面会使用
downloadInfoDao.deleteDownloadInfo(link)
sessionParamsDao.deleteSessionParams(link)
File(Const.DOWNLOADING_VIDEO_DIR, downloadingDirName).deleteRecursively()
downloadInfoDao.removeDownloadLinkByLink(link)
emit(Unit)
}.flowOn(Dispatchers.IO)
}
Expand Down
Loading

0 comments on commit c677eb0

Please sign in to comment.