package org.redcross.openmapkit;
import android.app.Activity;
import android.app.DownloadManager;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;
import com.mapbox.mapboxsdk.geometry.BoundingBox;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
/**
* Created by Nicholas Hallahan on 3/24/15.
* nhallahan@spatialdev.com
* * *
*/
public class OSMDownloader extends AsyncTask<Void, String, Long> {
private static final String OVERPASS_API_URL = "http://overpass-api.de/api/interpreter?data=";
private static final String PROGRESS_MSG = "Downloading OSM XML from Overpass API:\n\n";
private String queryTemplate = "(way[building]({{bbox}});node[~\".\"~\".\"]({{bbox}}););out%20meta;>;out%20meta%20qt;";
private String fileName = "overpass.osm";
private String statusMessage = "";
private long downloadId = -1;
private boolean downloading = true;
private int status = -1;
private Activity activity;
private BoundingBox bbox;
private DownloadManager downloadManager;
private ProgressDialog progressDialog;
private BroadcastReceiver broadcastReceiver;
/**
*
* @param activity the Activity that is calling the OSMDownloader
* @param bbox the bounding box the map is at
*/
public OSMDownloader(Activity activity, BoundingBox bbox) {
super();
this.activity = activity;
this.bbox = bbox;
downloadManager = (DownloadManager) activity.getSystemService(Activity.DOWNLOAD_SERVICE);
}
/**
*
* @param activity the Activity that is calling the OSMDownloader
* @param bbox the bounding box the map is at
* @param query the OverpassQL Query
* @param fileName the name of the file to be written to disk
*/
public OSMDownloader(Activity activity, BoundingBox bbox, String query, String fileName) {
this(activity, bbox);
this.queryTemplate = query;
this.fileName = fileName;
}
public void cancel() {
if (downloadId > -1) {
downloadManager.remove(downloadId);
}
}
@Override
protected void onPreExecute() {
setupProgressDialog();
}
/**
* This background thread is handling the updates for the progress bar.
* The actual downloading is happening in a separate system service (DownloadManager).
* * * *
* @param nothing
* @return
*/
@Override
protected Long doInBackground(Void... nothing) {
String query = composeQuery();
String url = OVERPASS_API_URL + query;
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDestinationInExternalPublicDir(ExternalStorage.getOSMDirRelativeToExternalDir(), fileName);
downloadId = downloadManager.enqueue(request);
pollDownloadManager();
return downloadId;
}
@Override
protected void onProgressUpdate(String... msgs) {
String msg = msgs[0];
progressDialog.setMessage(msg);
}
@Override
protected void onPostExecute(Long downloadId) {
if(progressDialog.isShowing()) {
progressDialog.dismiss();
}
// Download failed.
if (status != DownloadManager.STATUS_SUCCESSFUL) {
Toast toast = Toast.makeText(activity, statusMessage, Toast.LENGTH_LONG);
toast.show();
}
// Download successful, put it on the map.
else {
putCompletedDownloadOnMap();
}
}
protected String composeQuery() {
String bboxStr = bbox.getLatSouth() + "," +
bbox.getLonWest() + "," +
bbox.getLatNorth() + "," +
bbox.getLonEast();
return queryTemplate.replaceAll("\\{\\{bbox\\}\\}", bboxStr);
}
protected void setupProgressDialog() {
progressDialog = new ProgressDialog(activity);
progressDialog.setTitle("Downloading OSM Data");
progressDialog.setMessage("Starting download...");
progressDialog.setIndeterminate(true);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setCancelable(true);
progressDialog.show();
}
protected void pollDownloadManager() {
while (downloading) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
Cursor cursor = downloadManager.query(q);
cursor.moveToFirst();
final int bytesDownloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
final String msg = PROGRESS_MSG + ((double)bytesDownloaded) / 1000000.0 + " MB";
publishProgress(msg);
status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
statusMessage = statusMessage(cursor, bytesDownloaded);
Log.d("OSMDownloader", statusMessage);
if (status != DownloadManager.STATUS_PENDING && status != DownloadManager.STATUS_RUNNING) {
downloading = false;
}
// throttle the thread
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
protected String statusMessage(Cursor c, int bytesDownloaded) {
String msg;
switch (c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS))) {
case DownloadManager.STATUS_FAILED:
msg = "Download failed: " + bytesDownloaded + " bytes downloaded.";
break;
case DownloadManager.STATUS_PAUSED:
msg = "Download paused: " + bytesDownloaded + " bytes downloaded.";
break;
case DownloadManager.STATUS_PENDING:
msg = "Download pending: " + bytesDownloaded + " bytes downloaded.";
break;
case DownloadManager.STATUS_RUNNING:
msg = "Download in progress: " + bytesDownloaded + " bytes downloaded.";
break;
case DownloadManager.STATUS_SUCCESSFUL:
msg = "Download complete: " + bytesDownloaded + " bytes downloaded.";
break;
default:
msg = "STATUS MESSAGE ERROR";
break;
}
return (msg);
}
protected void putCompletedDownloadOnMap() {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
Cursor cursor = downloadManager.query(q);
cursor.moveToFirst();
String localFilename = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
Set<File> fileSet = new HashSet<>();
fileSet.add(new File(localFilename));
OSMMapBuilder.addOSMFilesToModel(fileSet);
}
}