diff --git a/android/src/com/mapswithme/maps/downloader/DownloadFilesTask.java b/android/src/com/mapswithme/maps/downloader/DownloadFilesTask.java new file mode 100644 index 0000000000..1144a1d433 --- /dev/null +++ b/android/src/com/mapswithme/maps/downloader/DownloadFilesTask.java @@ -0,0 +1,103 @@ +package com.mapswithme.maps.downloader; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.util.HashSet; + +import android.os.AsyncTask; + +// Checks if incomplete file exists and resumes it's download +// Downloads from scratch otherwise +class DownloadFilesTask extends AsyncTask +{ + public final HttpParams m_params; + // Stored here to remove finished tasks + private final HashSet m_activeTasks; + + DownloadFilesTask(final HttpParams params, HashSet activeTasks) + { + m_params = params; + m_activeTasks = activeTasks; + } + + @Override + protected void onPreExecute() + { + } + + @Override + protected void onPostExecute(IDownloadObserver.DownloadResult result) + { + m_activeTasks.remove(this); + m_params.m_observer.OnFinish(m_params, result); + } + + @Override + protected void onCancelled() + { + + } + + @Override + protected void onProgressUpdate(Long... progress) + { + m_params.m_observer.OnProgress(m_params, progress[0], progress[1]); + } + + @Override + protected IDownloadObserver.DownloadResult doInBackground(Void... p) + { + IDownloadObserver.DownloadResult retCode = IDownloadObserver.DownloadResult.EFailed; + try + { + retCode = downloadUrl(m_params); + } catch (IOException e) + { + } + return retCode; + } + + private IDownloadObserver.DownloadResult downloadUrl(HttpParams param) throws IOException + { + final File file = new File(new StringBuilder(m_params.m_fileToSave).append( + ".downloading").toString()); + final FileOutputStream os = new FileOutputStream(file, true); + + HttpURLConnection urlConnection = (HttpURLConnection) param.m_url + .openConnection(); + final long resumeFileLen = file.length(); + if (resumeFileLen > 0) + urlConnection.setRequestProperty("Range", new StringBuilder("bytes=%1-") + .append(resumeFileLen).toString()); + + try + { + final InputStream is = urlConnection.getInputStream(); + if (!param.m_url.getHost().equals(urlConnection.getURL().getHost())) + { + return IDownloadObserver.DownloadResult.ERedirected; + } + else + { + byte[] buffer = new byte[1024]; + int len; + final long totalLen = urlConnection.getContentLength(); + long sum = 0; + while ((len = is.read(buffer)) >= 0 && !isCancelled()) + { + os.write(buffer, 0, len); + sum += len; + publishProgress(sum, totalLen); + } + } + } + finally + { + urlConnection.disconnect(); + } + return IDownloadObserver.DownloadResult.EOk; + } +} diff --git a/android/src/com/mapswithme/maps/downloader/DownloadManager.java b/android/src/com/mapswithme/maps/downloader/DownloadManager.java new file mode 100644 index 0000000000..bf5d04d7c8 --- /dev/null +++ b/android/src/com/mapswithme/maps/downloader/DownloadManager.java @@ -0,0 +1,56 @@ +package com.mapswithme.maps.downloader; + +import java.net.URL; +import java.util.HashSet; +import java.util.Iterator; + +import android.util.Log; + +import com.mapswithme.maps.downloader.DownloadFilesTask; +import com.mapswithme.maps.downloader.HttpParams; + +public class DownloadManager +{ + private static final String TAG = "DownloadManager"; + + private static HashSet m_activeTasks = new HashSet(); + + public static void httpGet(URL url, String fileToSave, IDownloadObserver observer) + { + Iterator iterator = m_activeTasks.iterator(); + while (iterator.hasNext()) + { + if (iterator.next().m_params.m_url == url) + { + Log.w(TAG, "File is already downloading: " + url.toString()); + return; + } + } + final DownloadFilesTask task = new DownloadFilesTask(new HttpParams(url, fileToSave, observer), m_activeTasks); + m_activeTasks.add(task); + task.execute(); + } + + public static void cancelDownload(URL url) + { + Iterator iterator = m_activeTasks.iterator(); + while (iterator.hasNext()) + { + final DownloadFilesTask task = iterator.next(); + if (task.m_params.m_url == url) + { + task.cancel(false); + iterator.remove(); + break; + } + } + } + + public static void cancelAllDownloads() + { + Iterator iterator = m_activeTasks.iterator(); + while (iterator.hasNext()) + iterator.next().cancel(false); + m_activeTasks.clear(); + } +} diff --git a/android/src/com/mapswithme/maps/downloader/HttpParams.java b/android/src/com/mapswithme/maps/downloader/HttpParams.java new file mode 100644 index 0000000000..bb26084427 --- /dev/null +++ b/android/src/com/mapswithme/maps/downloader/HttpParams.java @@ -0,0 +1,17 @@ +package com.mapswithme.maps.downloader; + +import java.net.URL; + +public class HttpParams +{ + public final URL m_url; + public final String m_fileToSave; + public final IDownloadObserver m_observer; + + public HttpParams(URL url, String fileToSave, IDownloadObserver observer) + { + m_url = url; + m_fileToSave = fileToSave; + m_observer = observer; + } +} diff --git a/android/src/com/mapswithme/maps/downloader/IDownloadObserver.java b/android/src/com/mapswithme/maps/downloader/IDownloadObserver.java new file mode 100644 index 0000000000..3d27725173 --- /dev/null +++ b/android/src/com/mapswithme/maps/downloader/IDownloadObserver.java @@ -0,0 +1,14 @@ +package com.mapswithme.maps.downloader; + +public interface IDownloadObserver +{ + public enum DownloadResult + { + EOk, + EFailed, + ERedirected + } + + public abstract void OnFinish(final HttpParams params, final DownloadResult result); + public abstract void OnProgress(final HttpParams params, final Long current, final Long total); +}