Сохранение файлов из сети на диск в публичную директорию (Android)
// Archived from my old blog bibobo.ru and kept as it was, in Russian. Some of the APIs here are outdated.
Практически любому приложению, которое позволяет обмениваться контентом необходимо скачивать данные из сети и сохранять их на диск устройства. Существует два распространенных способа это сделать:
- Скачать и сохранить файл вручную;
- Использовать класс DownloadManager и доверить работу ему.
При этом скачанные файлы не будут видны приложениям на устройстве до тех пор, пока разработчик самостоятельно не сделает их доступными (либо до следующей перезагрузке устройства).
В этой статье мы рассмотрим ручной способ сохранения на диск применительно к Xamarin.Android. Более интересный вариант с использованием DownloadManager будет рассмотрен в другой статье.
Для начала необходимо получить массив байт файла из сети (например по его URL). Для этого можно использовать например простейший WebClient, написать примерно такой код:
string url = “url_к_нашему_файлу”;
byte[] dataBytes = new System.Net.WebClient().DownloadData(url);
Далее необходимо сохранить полученный массив байт как файл на диске. Для этого сначала необходимо получить путь до одной из публичных директорий, они могут быть следующими:
- Environment.DirectoryMusic;
- Environment.DirectoryPodcasts;
- Environment.DirectoryRingtones;
- Environment.DirectoryAlarms;
- Environment.DirectoryNotifications;
- Environment.DirectoryPictures;
- Environment.DirectoryMovies;
- Environment.DirectoryDownloads;
- Environment.DirectoryDcim.
Назначение директорий вполне ясно из их названия, будем использовать Environment.DirectoryDownloads. Напишем следующий код (пояснение в комментариях):
//получаем путь к директории с загрузками
string dirPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath;
//если директории нет (такое может быть, да О_о, создадим ее)
if (!Directory.Exists(dirPath))
{
Directory.CreateDirectory(dirPath);
}
//получаем путь до конечного файла в нашей директории, если он уже есть - удалим его
string filePath = Path.Combine(dirPath, file.Name);
if (File.Exists(filePath))
{
File.Delete(filePath);
}
//записываем массив байт на диск
File.WriteAllBytes(filePath, fileBytes);
Почти готово, осталось только объявить системе о том, что на диске теперь есть новый файл, доступный всем вокруг. Для этого используется подсистема Android, которая называется MediaScanner. Существует несколько способов работы с МедиаСканнером, все они обладают разным уровнем гибкости и сложности. Мы воспользуемся самым простым — отправим широковещательный интент системе, МедиаСканнер его поймает и сделает добавит файл в свою базу.
//объявим МедиаСканеру о том, что появился новый файл
Intent mediaScannerIntent = new Intent(Intent.ActionMediaScannerScanFile);
mediaScannerIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(filePath)));
SendBroadcast(mediaScannerIntent);