<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0">

<channel>

<title>Just Developer Blog, заметки с тегом: загрузка файлов</title>
<link>http://bibobo.ru/tags/zagruzka-faylov/</link>
<description></description>
<generator>E2 (v3254; Aegea)</generator>

<item>
<title>Реализация уведомлений-индикаторов для загружаемых на сервер файлов (Android)</title>
<guid isPermaLink="true">http://bibobo.ru/all/realizaciya-uvedomleniy-indikatorov-dlya-zagruzhaemyh-na-server/</guid>
<link>http://bibobo.ru/all/realizaciya-uvedomleniy-indikatorov-dlya-zagruzhaemyh-na-server/</link>
<comments>http://bibobo.ru/all/realizaciya-uvedomleniy-indikatorov-dlya-zagruzhaemyh-na-server/</comments>
<description>&lt;p&gt;При необходимости загрузить файла на сервер из приложения встает вопрос об индикации процесса загрузки. Если дизайн позволяет то можно отобразить диалог прогресс бара (при этом заблокировать интерфейс пользователя). Но на мой взгляд более интересным вариантом индикации являются уведомления в статус баре системы, которые нельзя смахнуть.&lt;/p&gt;
&lt;p&gt;&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;При реализации такого подхода может возникнуть несколько проблем:&lt;/p&gt;
&lt;p&gt;&lt;/br&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Как создать уведомление для каждого загружаемого файла (если например существует возможность единовременно загружать несколько файлов)&lt;/li&gt;
&lt;li&gt;Как программно отменить уведомление после завершения процесса загрузки на сервер&lt;br /&gt;
&lt;input id="button_android_download_file_notification" type="button" onclick="toggle(cut_android_download_file_notification, button_android_download_file_notification)" value="Читать дальше" hiddenText="Свернуть" visibleText="Читать дальше"&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div id="cut_android_download_file_notification" style="display: none;" displayOld=""&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Для решения этих проблем необходимо знать как система индексирует уведомления, создаваемые приложением. Каждое приложение может создать сколь угодно много уведомлений, но чтобы иметь возможность обновить определенное уведомление, либо отменить его — необходимо присвоить каждому из уведомлений свой уникальный ID. Ниже код реализации создания уведомления при старте загрузки файла на сервер и его отмены, по окончании загрузки:&lt;/p&gt;
&lt;p&gt;&lt;/br&gt;&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;//Кеш, хранящий список id активных на данный момент уведомлений
private List&amp;lt;int&amp;gt; _notificationCache = new List&amp;lt;int&amp;gt;();

private void UploadFile()
{
    //получим рандомный ID для уведомления, при этом он не должен пересекаться с уже существующими (для этого используем кеш)
    Random r = new Random(System.Environment.TickCount);
    int notificationId = 0;
    while (notificationId == 0 || _notificationCache.Contains(notificationId))
    {
        notificationId = r.Next(1, 1000);
    }
    _notificationCache.Add(notificationId);
    //
                
    Notification.Builder builder = new Notification.Builder(Activity);
    builder.SetSmallIcon(Resource.Drawable.file_32x32)
        //устанавливаем заголовок для уведомления
        .SetContentTitle(filename)
        //в дескрипшне будет храниться наша строка &amp;quot;Загружаю файл на сервер...&amp;quot;
        .SetContentText(Activity.GetString(Resource.String.attachement_uploading))
        .SetAutoCancel(false)
        //запрещаем отмену уведомления пользователем
        .SetOngoing(true)
        //разрешаем уведомлению появиться в статус баре, мигать светодиодом и т.п.
        .SetDefaults(NotificationDefaults.All);

    NotificationManager manager = (NotificationManager)Activity.GetSystemService(Activity.NotificationService);
    manager.Notify(notificationId, builder.Build());

    //////////////////////////////////////////
    // ... код загрузки файла на сервер ... //
    //////////////////////////////////////////

    //отменяем уведомление и удаляем его ID из кеша
    manager.Cancel(notificationId);
    _notificationCache.Remove(notificationId);
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
<pubDate>Sun, 20 Dec 2015 12:53:09 +0300</pubDate>
</item>

<item>
<title>Использование DownloadManager для скачивания файлов из сети (Android)</title>
<guid isPermaLink="true">http://bibobo.ru/all/ispolzovanie-downloadmanager-dlya-skachivaniya-faylov-iz-seti-an/</guid>
<link>http://bibobo.ru/all/ispolzovanie-downloadmanager-dlya-skachivaniya-faylov-iz-seti-an/</link>
<comments>http://bibobo.ru/all/ispolzovanie-downloadmanager-dlya-skachivaniya-faylov-iz-seti-an/</comments>
<description>&lt;p&gt;В прошлой статье я рассказывал о том, как скачивать файлы из сети и сохранять их на диск, а так же использовать &lt;i&gt;MediaScanner&lt;/i&gt; для того, чтобы сделать файлы доступными другим приложениям (например галерее, если это фотография или видео).&lt;/p&gt;
&lt;p&gt;&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;Сегодня же хотелось бы рассказать о более интересном и предпочтительном способе скачивания файлов — использовании системного сервиса &lt;i&gt;DownloadManager&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;DownloadManager это такой сервис платформы Android, который предоставляет весь спектр функциональности, связанной с загрузкой файлов. Он сам начнет скачивание, корректно отреагирует на обрыв связи или смену типа сети, запустит скачивание по новой (если был обрыв связи), создаст и отобразит уведомление о загрузке файла, уведомит &lt;i&gt;MediaScanner&lt;/i&gt; о том, что файл загружен и многое другое.&lt;/p&gt;
&lt;p&gt;&lt;input id="button_android_download_save_file2" type="button" onclick="toggle(cut_android_download_save_file2, button_android_download_save_file2)" value="Читать дальше" hiddenText="Свернуть" visibleText="Читать дальше"&gt;&lt;/p&gt;
&lt;div id="cut_android_download_save_file2" style="display: none;" displayOld=""&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Для корректного использования &lt;i&gt;DownloadManager&lt;/i&gt; нам понадобится:&lt;/p&gt;
&lt;p&gt;&lt;/br&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Создать свой класс — наследник &lt;i&gt;BroadcastReceiver&lt;/i&gt;, в котором мы будем реагировать на интенты, отсылаемые &lt;i&gt;DownloadManager&lt;/i&gt;’ом;&lt;/li&gt;
&lt;li&gt;Подготовить URI с ресурсом, который нужно загрузить;&lt;/li&gt;
&lt;li&gt;Создать реквест с нашим URI и другими настройками &lt;i&gt;DownloadManager&lt;/i&gt;;&lt;/li&gt;
&lt;li&gt;Запустить скачивание.&lt;br /&gt;
&lt;/br&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Итак перво наперво — напишем класс-наследник &lt;i&gt;BroadcastReceiver&lt;/i&gt; и реализуем логику, которая покажет Toast, когда наш файл скачается:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// Ресивер, который принимает информацию о состоянии загружаемых файлов приложением (задача только одна - отобразить сообщение об успешной загрузке)
/// &amp;lt;/summary&amp;gt;
public class DownloadManagerReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        if (intent.Action == DownloadManager.ActionDownloadComplete)
        {
            //это не совсем правильно с точки зрения производительности, лучше передать ссылку на менеджер извне
            DownloadManager downloadManager = (DownloadManager)context.GetSystemService(Activity.DownloadService);

            long downloadId = intent.GetLongExtra(DownloadManager.ExtraDownloadId, -1);
            if (downloadId == -1)
            {
                return;
            }

            DownloadManager.Query query = new DownloadManager.Query();
            query.SetFilterById(new long[]{ downloadId });

            ICursor cursor = downloadManager.InvokeQuery(query);
            if (cursor != null &amp;amp;&amp;amp; cursor.MoveToFirst())
            {
                if (DownloadStatus.Successful == (DownloadStatus)cursor.GetInt(cursor.GetColumnIndex(DownloadManager.ColumnStatus)))
                {
                    string filename = cursor.GetString(cursor.GetColumnIndex(DownloadManager.ColumnTitle));
                    
                    Toast.makeText(context, string.Format(context.GetString(Resource.String.chat_attachement_succesfully_downloaded), filename), Toast.LENGTH_SHORT);
                }
            }

        }
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;Далее необходимо создать и зарегистрировать наш ресивер:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;protected override async void OnCreate(Bundle bundle)
{
    //код инициализации активности
    //...
    /////////

    //создаем ресивер для корректной обработки успешного скачивания файла
    _downloadManagerReceiver = new DownloadManagerReceiver();
    RegisterReceiver(_downloadManagerReceiver, new IntentFilter(DownloadManager.ActionDownloadComplete));
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;Последним этапом — необходимо получить ссылку на экземпляр сервиса &lt;i&gt;DownloadService&lt;/i&gt;, настроить менеджер и запустить скачивание:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;private void DownloadFile(string filename){
    DownloadManager downloadManager = (DownloadManager)GetSystemService(Activity.DownloadService);
    //реквест содержит URI файла и дополнительные настройки DownloadManager'а
    DownloadManager.Request request = new DownloadManager.Request(Android.Net.Uri.Parse(&amp;quot;http://наш_url_для_скачивания&amp;quot;));

    //нотификейшн будет виден всегда, пока юзер не отменит его вручную или не кликнет
    request.SetNotificationVisibility(DownloadVisibility.VisibleNotifyCompleted);
    //задаем публичную директорию с загрузками и вторым параметром имя файла + расширение
    request.SetDestinationInExternalPublicDir(Android.OS.Environment.DirectoryDownloads, filename);
    //разрешаем сканить новый файл МедиаСканнеру
    request.AllowScanningByMediaScanner();

    //запускаем скачивание
    downloadManager.Enqueue(request);   
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;Вот и все, после старта скачивания менеджер создать нотификейшн со статусом скачивания, а после позволит открыть файл в приложении по-умолчанию.&lt;/p&gt;
&lt;/div&gt;</description>
<pubDate>Mon, 07 Dec 2015 22:12:40 +0300</pubDate>
</item>

<item>
<title>Сохранение файлов из сети на диск в публичную директорию (Android)</title>
<guid isPermaLink="true">http://bibobo.ru/all/sohranenie-faylov-iz-seti-na-disk-v-publichnuyu-direktoriyu-andr/</guid>
<link>http://bibobo.ru/all/sohranenie-faylov-iz-seti-na-disk-v-publichnuyu-direktoriyu-andr/</link>
<comments>http://bibobo.ru/all/sohranenie-faylov-iz-seti-na-disk-v-publichnuyu-direktoriyu-andr/</comments>
<description>&lt;p&gt;Практически любому приложению, которое позволяет обмениваться контентом необходимо скачивать данные из сети и сохранять их на диск устройства. Существует два распространенных способа это сделать:&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Скачать и сохранить файл вручную;&lt;/li&gt;
&lt;li&gt;Использовать класс &lt;i&gt;DownloadManager&lt;/i&gt; и доверить работу ему.&lt;br /&gt;
&lt;br/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;При этом скачанные файлы не будут видны приложениям на устройстве до тех пор, пока разработчик самостоятельно не сделает их доступными (либо до следующей перезагрузке устройства).&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;В этой статье мы рассмотрим ручной способ сохранения на диск применительно к Xamarin.Android. Более интересный вариант с использованием &lt;i&gt;DownloadManager&lt;/i&gt; будет рассмотрен в другой статье.&lt;/p&gt;
&lt;p&gt;&lt;input id="button_android_download_save_file1" type="button" onclick="toggle(cut_android_download_save_file1, button_android_download_save_file1)" value="Читать дальше" hiddenText="Свернуть" visibleText="Читать дальше"&gt;&lt;/p&gt;
&lt;div id="cut_android_download_save_file1" style="display: none;" displayOld=""&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Для начала необходимо получить массив байт файла из сети (например по его URL). Для этого можно использовать например простейший &lt;i&gt;WebClient&lt;/i&gt;, написать примерно такой код:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;string url = “url_к_нашему_файлу”;
byte[] dataBytes = new System.Net.WebClient().DownloadData(url);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Далее необходимо сохранить полученный массив байт как файл на диске. Для этого сначала необходимо получить путь до одной из публичных директорий, они могут быть следующими:&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Environment.DirectoryMusic;&lt;/li&gt;
&lt;li&gt;Environment.DirectoryPodcasts;&lt;/li&gt;
&lt;li&gt;Environment.DirectoryRingtones;&lt;/li&gt;
&lt;li&gt;Environment.DirectoryAlarms;&lt;/li&gt;
&lt;li&gt;Environment.DirectoryNotifications;&lt;/li&gt;
&lt;li&gt;Environment.DirectoryPictures;&lt;/li&gt;
&lt;li&gt;Environment.DirectoryMovies;&lt;/li&gt;
&lt;li&gt;Environment.DirectoryDownloads;&lt;/li&gt;
&lt;li&gt;Environment.DirectoryDcim.&lt;br /&gt;
&lt;br/&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Назначение директорий вполне ясно из их названия, будем использовать &lt;i&gt;Environment.DirectoryDownloads&lt;/i&gt;. Напишем следующий код (пояснение в комментариях):&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;//получаем путь к директории с загрузками
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);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Почти готово, осталось только объявить системе о том, что на диске теперь есть новый файл, доступный всем вокруг. Для этого используется подсистема Android, которая называется &lt;i&gt;MediaScanner&lt;/i&gt;. Существует несколько способов работы с МедиаСканнером, все они обладают разным уровнем гибкости и сложности. Мы воспользуемся самым простым — отправим широковещательный интент системе, МедиаСканнер его поймает и сделает добавит файл в свою базу.&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;//объявим МедиаСканеру о том, что появился новый файл
Intent mediaScannerIntent = new Intent(Intent.ActionMediaScannerScanFile);
mediaScannerIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(filePath)));
SendBroadcast(mediaScannerIntent);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
<pubDate>Wed, 02 Dec 2015 22:06:16 +0300</pubDate>
</item>


</channel>
</rss>