Требуется разработать приложение, реализующее видеоплеер со следующим функциональными элементами:
- Видеоплеер
- Поле для ввода http ссылки на видеофайл.
- Кнопка "Play/Pause" для приостановки/продолжения воспроизведения.
- Кнопка "Download", при нажатии на которую начинается загрузка текущего видеофайла (с отображением прогресса загрузки). После удачной загрузки при старте воспроизведения той же самой ссылки должен открываться уже загруженный файл. Можно не загружать файлы в формате m3u8, достаточно отобразить ошибку.
Язык разработки: Kotlin/Java.
В качестве видео плеера был использован стандартный класс MediaPlayer из Android SDK, т.к. для простого воспроизведения видео он подходит. Для более сложных случаев, например воспроизведение различных форматов таких как HLS, DASH возможно использовать ExoPlayer. Также ExoPlayer позволяет гибче настраивать управление воспроизведением, но имеет более сложное API в использовании.
В поле ввода возможно вводить http/https ссылки. Другие протоколы не поддерживаются. Если во время воспроизведения ввести что-либо в поле ввода, то воспроизведение видео останавливается. Если попытаться воспроизвести видео по ссылке не http/https протокола будет показана ошибка.
Логика работы кнопка "Play/Pause" была реализована следующим образом (как показаном на диаграмме):
4.Кнопка "Download", при нажатии на которую начинается загрузка текущего видеофайла (с отображением прогресса загрузки). После удачной загрузки при старте воспроизведения той же самой ссылки должен открываться уже загруженный файл. Можно не загружать файлы в формате m3u8, достаточно отобразить ошибку.
Для загрузки видео файла был использован DownloadManager. Это отдельный системный сервис, который способен выполнять задачи загрузки файлов. Он может сохранять файлы только в публичные папки и не может в приватную папку приложения, т.к. у него нет прав записи туда. Для данной задачи такое ограничение было приемлимым.
Основная часть бизнес логики находится в классах из пакета download
, но также и в MainViewModel
. Как вьюмодель, так и остальные классы бизнес логики возможно покрыть тестами, замокав зависимости, передаваемые в конструктор.
Например, MainViewModel#onPlayPauseClicked(url: String)
можно протестировать следующим образом:
- передаем моки зависимостей
private val downloadHelper: DownloadHelper,
private val downloadStorage: DownloadStorage,
private val downloadErrorHandler: DownloadErrorHandler
в конструктор
-
Добавляем подписчиков на
videoUri
livedata -
Указываем моку downloadStorage при вызове
hasDownload(url)
возвращать false -
Проверяем что подписчик на
videoUri
livedata получил верный uri, соответствующий url переданный в методMainViewModel
-
Проверяем что
hasDownload(url)
уdownloadStorage
был вызван и никакие другие методы вызваны не были.
Аналогичным образом можно протестировать и другие методы/случаи вьюмодели.