Files
neomovies-mobile/android/torrentengine
factory-droid[bot] 1b28c5da45 feat: Add TorrentEngine library and new API client
- Created complete TorrentEngine library module with LibTorrent4j
  - Full torrent management (add, pause, resume, remove)
  - Magnet link metadata extraction
  - File priority management (even during download)
  - Foreground service with persistent notification
  - Room database for state persistence
  - Reactive Flow API for UI updates

- Integrated TorrentEngine with MainActivity via MethodChannel
  - addTorrent, getTorrents, pauseTorrent, resumeTorrent, removeTorrent
  - setFilePriority for dynamic file selection
  - Full JSON serialization for Flutter communication

- Created new NeoMoviesApiClient for Go-based backend
  - Email verification flow (register, verify, resendCode)
  - Google OAuth support
  - Torrent search via RedAPI
  - Multiple player support (Alloha, Lumex, Vibix)
  - Enhanced reactions system (likes/dislikes)
  - All movies/TV shows endpoints

- Updated dependencies and build configuration
  - Java 17 compatibility
  - Updated Kotlin coroutines to 1.9.0
  - Fixed build_runner version conflict
  - Added torrentengine module to settings.gradle.kts

- Added comprehensive documentation
  - TorrentEngine README with usage examples
  - DEVELOPMENT_SUMMARY with full implementation details
  - ProGuard rules for library

This is a complete rewrite of torrent functionality as a reusable library.
2025-10-02 10:56:22 +00:00
..

TorrentEngine Library

Мощная библиотека для Android, обеспечивающая полноценную работу с торрентами через LibTorrent4j.

🎯 Возможности

  • Загрузка из magnet-ссылок - получение метаданных и загрузка файлов
  • Выбор файлов - возможность выбирать какие файлы загружать до и во время загрузки
  • Управление приоритетами - изменение приоритета файлов в активной раздаче
  • Фоновый сервис - непрерывная работа в фоне с foreground уведомлением
  • Постоянное уведомление - нельзя закрыть пока активны загрузки
  • Персистентность - сохранение состояния в Room database
  • Реактивность - Flow API для мониторинга изменений
  • Полная статистика - скорость, пиры, сиды, прогресс, ETA
  • Pause/Resume/Remove - полный контроль над раздачами

📦 Установка

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()

📱 Интеграция с Flutter

Создайте MethodChannel для вызова из Flutter:

class TorrentEngineChannel(private val context: Context) {
    private val torrentEngine = TorrentEngine.getInstance(context)
    private val channel = "com.neomovies/torrent"
    
    fun setupMethodChannel(flutterEngine: FlutterEngine) {
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel)
            .setMethodCallHandler { call, result ->
                when (call.method) {
                    "addTorrent" -> {
                        val magnetUri = call.argument<String>("magnetUri")!!
                        val savePath = call.argument<String>("savePath")!!
                        
                        CoroutineScope(Dispatchers.IO).launch {
                            try {
                                val hash = torrentEngine.addTorrent(magnetUri, savePath)
                                result.success(hash)
                            } catch (e: Exception) {
                                result.error("ERROR", e.message, null)
                            }
                        }
                    }
                    // ... другие методы
                }
            }
    }
}

📄 Лицензия

MIT License - используйте свободно в любых проектах!

🤝 Вклад

Библиотека разработана как универсальное решение для работы с торрентами в Android. Может использоваться в любых проектах без ограничений.

🐛 Известные проблемы

  • LibTorrent4j требует минимум Android 5.0 (API 21)
  • Для Android 13+ нужно запрашивать POST_NOTIFICATIONS permission
  • Foreground service требует отображения уведомления

📞 Поддержка

При возникновении проблем создайте issue с описанием и логами.