Files
neomovies-mobile/android/torrentengine
factory-droid[bot] 3e664d726b Complete Kotlin compatibility fixes and dependency updates
- Update kotlinx-coroutines from 1.9.0 to 1.10.1 in all modules
- Add legacy settings.gradle file for CI compatibility
- Update kotlin-coroutines in app/build.gradle.kts
- Update kotlin-coroutines in torrentengine/build.gradle.kts

This resolves all remaining Kotlin version incompatibility issues:
- Main Kotlin plugin: 1.9.24 → 2.1.0 (done previously)
- Coroutines library: 1.9.0 → 1.10.1 (this commit)
- CI compatibility: added settings.gradle alongside settings.gradle.kts

Build now passes Kotlin compatibility checks and only fails on
NDK license issues which are environment-specific, not code issues.
2025-10-03 13:06:53 +00:00
..
2025-10-02 17:09:36 +00:00
2025-10-02 17:09:36 +00:00
2025-10-02 17:09:36 +00:00

TorrentEngine Library

Либа для моего клиента и других независимых проектов где нужен простой торрент движок.

Установка

1. Добавьте модуль в settings.gradle.kts:

include(":torrentengine")

2. Добавьте зависимость в app/build.gradle.kts:

dependencies {
    implementation(project(":torrentengine"))
}

3. Добавьте permissions в AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

Использование

Инициализация

val torrentEngine = TorrentEngine.getInstance(context)
torrentEngine.startStatsUpdater() // Запустить обновление статистики

Добавление торрента

lifecycleScope.launch {
    try {
        val magnetUri = "magnet:?xt=urn:btih:..."
        val savePath = "${context.getExternalFilesDir(null)}/downloads"
        
        val infoHash = torrentEngine.addTorrent(magnetUri, savePath)
        Log.d("Torrent", "Added: $infoHash")
    } catch (e: Exception) {
        Log.e("Torrent", "Failed to add", e)
    }
}

Получение списка торрентов (реактивно)

lifecycleScope.launch {
    torrentEngine.getAllTorrentsFlow().collect { torrents ->
        torrents.forEach { torrent ->
            println("${torrent.name}: ${torrent.progress * 100}%")
            println("Speed: ${torrent.downloadSpeed} B/s")
            println("Peers: ${torrent.numPeers}, Seeds: ${torrent.numSeeds}")
            println("ETA: ${torrent.getFormattedEta()}")
        }
    }
}

Управление файлами в раздаче

lifecycleScope.launch {
    // Получить информацию о торренте
    val torrent = torrentEngine.getTorrent(infoHash)
    
    torrent?.files?.forEachIndexed { index, file ->
        println("File $index: ${file.path} (${file.size} bytes)")
        
        // Выбрать только видео файлы
        if (file.isVideo()) {
            torrentEngine.setFilePriority(infoHash, index, FilePriority.HIGH)
        } else {
            torrentEngine.setFilePriority(infoHash, index, FilePriority.DONT_DOWNLOAD)
        }
    }
}

Пауза/Возобновление/Удаление

lifecycleScope.launch {
    // Поставить на паузу
    torrentEngine.pauseTorrent(infoHash)
    
    // Возобновить
    torrentEngine.resumeTorrent(infoHash)
    
    // Удалить (с файлами или без)
    torrentEngine.removeTorrent(infoHash, deleteFiles = true)
}

Множественное изменение приоритетов

lifecycleScope.launch {
    val priorities = mapOf(
        0 to FilePriority.MAXIMUM,  // Первый файл - максимальный приоритет
        1 to FilePriority.HIGH,      // Второй - высокий
        2 to FilePriority.DONT_DOWNLOAD // Третий - не загружать
    )
    
    torrentEngine.setFilePriorities(infoHash, priorities)
}

Модели данных

TorrentInfo

data class TorrentInfo(
    val infoHash: String,
    val magnetUri: String,
    val name: String,
    val totalSize: Long,
    val downloadedSize: Long,
    val uploadedSize: Long,
    val downloadSpeed: Int,
    val uploadSpeed: Int,
    val progress: Float,
    val state: TorrentState,
    val numPeers: Int,
    val numSeeds: Int,
    val savePath: String,
    val files: List<TorrentFile>,
    val addedDate: Long,
    val finishedDate: Long?,
    val error: String?
)

TorrentState

enum class TorrentState {
    STOPPED,
    QUEUED,
    METADATA_DOWNLOADING,
    CHECKING,
    DOWNLOADING,
    SEEDING,
    FINISHED,
    ERROR
}

FilePriority

enum class FilePriority(val value: Int) {
    DONT_DOWNLOAD(0),  // Не загружать
    LOW(1),            // Низкий приоритет
    NORMAL(4),         // Обычный (по умолчанию)
    HIGH(6),           // Высокий
    MAXIMUM(7)         // Максимальный (загружать первым)
}

Foreground Service

Сервис автоматически запускается при добавлении торрента и показывает постоянное уведомление с:

  • Количеством активных торрентов
  • Общей скоростью загрузки/отдачи
  • Списком загружающихся файлов с прогрессом
  • Кнопками управления (Pause All)

Уведомление нельзя закрыть пока есть активные торренты.

Персистентность

Все торренты сохраняются в Room database и автоматически восстанавливаются при перезапуске приложения.

Проверка видео файлов

val videoFiles = torrent.files.filter { it.isVideo() }

Получение share ratio

val ratio = torrent.getShareRatio()

Подсчет выбранных файлов

val selectedCount = torrent.getSelectedFilesCount()
val selectedSize = torrent.getSelectedSize()

Apache License 2.0.

Made with <3 by Erno/Foxix