implement batch tile downloader for android client
git-svn-id: https://osmand.googlecode.com/svn/trunk@762 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
parent
6605875694
commit
b180b6bd70
12 changed files with 294 additions and 11 deletions
|
@ -2,7 +2,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="net.osmand" android:versionName="0.5.1" android:versionCode="22" android:installLocation="auto">
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name"
|
||||
android:debuggable="false" android:name=".activities.OsmandApplication" android:description="@string/app_description">
|
||||
android:debuggable="true" android:name=".activities.OsmandApplication" android:description="@string/app_description">
|
||||
<activity android:name=".activities.MainMenuActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
|
||||
<LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="center_horizontal" >
|
||||
<LinearLayout android:layout_height="wrap_content" android:layout_width="wrap_content"
|
||||
android:background="@drawable/headliner" android:orientation="horizontal" >
|
||||
android:background="@drawable/headliner" android:orientation="horizontal" android:id="@+id/Headliner" >
|
||||
<ImageView android:src="@drawable/headline_osmand_icon"
|
||||
android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_marginLeft="5dp"/>
|
||||
<TextView android:layout_height="wrap_content" android:layout_width="wrap_content"
|
||||
|
|
25
OsmAnd/res/layout/download_tiles.xml
Normal file
25
OsmAnd/res/layout/download_tiles.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" android:orientation="vertical">
|
||||
<TextView android:text="@string/select_max_zoom_preload_area" android:gravity="center"
|
||||
android:layout_width="fill_parent" android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="5dp"/>
|
||||
<SeekBar android:id="@+id/ZoomToDownload" android:layout_width="fill_parent" android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="5dp"/>
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent" android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="5dp">
|
||||
<TextView android:text="10" android:gravity="left" android:layout_weight="0.5" android:id="@+id/MinZoom"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
<TextView android:text="15" android:gravity="right" android:layout_weight="0.5" android:id="@+id/MaxZoom"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
<TextView android:text="@string/tiles_to_download_estimated_size" android:gravity="center" android:id="@+id/DownloadDescription"
|
||||
android:layout_width="fill_parent" android:layout_height="wrap_content"/>
|
||||
<ImageView android:layout_width="fill_parent" android:layout_height="fill_parent"
|
||||
android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:id="@+id/AreaPreview"/>
|
||||
</LinearLayout>
|
|
@ -8,7 +8,7 @@
|
|||
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
|
||||
<LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="center_horizontal" >
|
||||
<LinearLayout android:layout_height="wrap_content" android:layout_width="wrap_content"
|
||||
android:background="@drawable/headliner" android:orientation="horizontal" >
|
||||
android:background="@drawable/headliner" android:orientation="horizontal" android:id="@+id/Headliner" >
|
||||
<ImageView android:src="@drawable/headline_osmand_icon"
|
||||
android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_marginLeft="5dp"/>
|
||||
<TextView android:layout_height="wrap_content" android:layout_width="wrap_content"
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="tiles_to_download_estimated_size">На масштабе {0} загрузить {1} тайлов ({2} Mb )</string>
|
||||
<string name="context_menu_item_download_map">Загрузить карту</string>
|
||||
<string name="select_max_zoom_preload_area">Выберите максимальный масштаб для загрузки видимой области</string>
|
||||
<string name="maps_could_not_be_downloaded">Выбранная карта не может быть загружена</string>
|
||||
<string name="continuous_rendering">Быстрый рендеринг</string>
|
||||
<string name="continuous_rendering_descr">Выберите способ как отрисовывать карту</string>
|
||||
<string name="rendering_exception">Во время отображения карты произошла непредвиденная ошибка</string>
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<resources>
|
||||
<string name="tiles_to_download_estimated_size">At zoom {0} download {1} tiles ({2} Mb )</string>
|
||||
<string name="context_menu_item_download_map">Download map</string>
|
||||
<string name="select_max_zoom_preload_area">Select max zoom to preload visible area</string>
|
||||
<string name="maps_could_not_be_downloaded">This map could not be downloaded</string>
|
||||
|
||||
<string name="continuous_rendering">Continuous rendering</string>
|
||||
<string name="continuous_rendering_descr">Choose show continuous rendering or whole image</string>
|
||||
<string name="rendering_exception">Error occurred while rendering selected area</string>
|
||||
|
|
|
@ -656,6 +656,10 @@ public class ResourceManager {
|
|||
closeTransport();
|
||||
}
|
||||
|
||||
public synchronized void reloadTilesFromFS(){
|
||||
imagesOnFS.clear();
|
||||
}
|
||||
|
||||
/// On low memory method ///
|
||||
public void onLowMemory() {
|
||||
log.info("On low memory : cleaning tiles - size = " + cacheOfImages.size()); //$NON-NLS-1$
|
||||
|
|
|
@ -96,7 +96,7 @@ public class TransportIndexRepositoryBinary implements TransportIndexRepository
|
|||
for(int r : stop.getReferencesToRoutes()) {
|
||||
try {
|
||||
TransportRoute route = file.getTransportRoute(r);
|
||||
res.add(f.format(new String[] { route.getRef(), route.getType(), route.getName(), route.getEnName()}));
|
||||
res.add(f.format(new String[] { route.getRef()+"", route.getType()+"", route.getName()+"", route.getEnName()+""})); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
} catch (IOException e) {
|
||||
log.error("Disk error ", e); //$NON-NLS-1$
|
||||
}
|
||||
|
|
|
@ -629,6 +629,7 @@ public class DownloadIndexActivity extends ListActivity {
|
|||
if (lowerCase.contains("map")) { //$NON-NLS-1$
|
||||
if (!f) {
|
||||
s += ", "; //$NON-NLS-1$
|
||||
} else {
|
||||
f = false;
|
||||
}
|
||||
s += getString(R.string.map_index);
|
||||
|
@ -636,6 +637,7 @@ public class DownloadIndexActivity extends ListActivity {
|
|||
if (lowerCase.contains("transport")) { //$NON-NLS-1$
|
||||
if (!f) {
|
||||
s += ", "; //$NON-NLS-1$
|
||||
} else {
|
||||
f = false;
|
||||
}
|
||||
s += getString(R.string.transport);
|
||||
|
@ -643,6 +645,7 @@ public class DownloadIndexActivity extends ListActivity {
|
|||
if (lowerCase.contains("address")) { //$NON-NLS-1$
|
||||
if (!f) {
|
||||
s += ", "; //$NON-NLS-1$
|
||||
} else {
|
||||
f = false;
|
||||
}
|
||||
s += getString(R.string.address);
|
||||
|
|
235
OsmAnd/src/net/osmand/activities/DownloadTilesDialog.java
Normal file
235
OsmAnd/src/net/osmand/activities/DownloadTilesDialog.java
Normal file
|
@ -0,0 +1,235 @@
|
|||
package net.osmand.activities;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.R;
|
||||
import net.osmand.ResourceManager;
|
||||
import net.osmand.data.preparation.MapTileDownloader;
|
||||
import net.osmand.data.preparation.MapTileDownloader.DownloadRequest;
|
||||
import net.osmand.data.preparation.MapTileDownloader.IMapDownloaderCallback;
|
||||
import net.osmand.map.ITileSource;
|
||||
import net.osmand.osm.MapUtils;
|
||||
import net.osmand.views.OsmandMapTileView;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class DownloadTilesDialog {
|
||||
|
||||
|
||||
private final static Log log = LogUtil.getLog(DownloadTilesDialog.class);
|
||||
private final Context ctx;
|
||||
private final OsmandApplication app;
|
||||
private final OsmandMapTileView mapView;
|
||||
|
||||
public DownloadTilesDialog(Context ctx, OsmandApplication app, OsmandMapTileView mapView){
|
||||
this.ctx = ctx;
|
||||
this.app = app;
|
||||
this.mapView = mapView;
|
||||
}
|
||||
|
||||
|
||||
public void openDialog(){
|
||||
final ITileSource mapSource = mapView.getMap();
|
||||
if(mapSource == null || !mapSource.couldBeDownloadedFromInternet()){
|
||||
Toast.makeText(ctx, R.string.maps_could_not_be_downloaded, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
final int max = mapSource.getMaximumZoomSupported();
|
||||
final int zoom = mapView.getZoom();
|
||||
|
||||
// calculate pixel rectangle
|
||||
Rect boundsRect = new Rect(0, 0, mapView.getWidth(), mapView.getHeight());
|
||||
float tileX = (float) MapUtils.getTileNumberX(zoom, mapView.getLongitude());
|
||||
float tileY = (float) MapUtils.getTileNumberY(zoom, mapView.getLatitude());
|
||||
float w = mapView.getCenterPointX();
|
||||
float h = mapView.getCenterPointY();
|
||||
RectF tilesRect = new RectF();
|
||||
final RectF latlonRect = new RectF();
|
||||
mapView.calculateTileRectangle(boundsRect, w, h, tileX, tileY, tilesRect);
|
||||
|
||||
latlonRect.top = (float) MapUtils.getLatitudeFromTile(zoom, tilesRect.top);
|
||||
latlonRect.left = (float) MapUtils.getLongitudeFromTile(zoom, tilesRect.left);
|
||||
latlonRect.bottom = (float) MapUtils.getLatitudeFromTile(zoom, tilesRect.bottom);
|
||||
latlonRect.right = (float) MapUtils.getLongitudeFromTile(zoom, tilesRect.right);
|
||||
|
||||
Builder builder = new AlertDialog.Builder(ctx);
|
||||
LayoutInflater inflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
View view = inflater.inflate(R.layout.download_tiles, null);
|
||||
|
||||
|
||||
|
||||
((TextView)view.findViewById(R.id.MinZoom)).setText(zoom+""); //$NON-NLS-1$
|
||||
((TextView)view.findViewById(R.id.MaxZoom)).setText(max+""); //$NON-NLS-1$
|
||||
final SeekBar seekBar = (SeekBar) view.findViewById(R.id.ZoomToDownload);
|
||||
seekBar.setMax(max - zoom);
|
||||
seekBar.setProgress((max - zoom) / 2);
|
||||
|
||||
final TextView downloadText = ((TextView) view.findViewById(R.id.DownloadDescription));
|
||||
final String template = ctx.getString(R.string.tiles_to_download_estimated_size);
|
||||
|
||||
|
||||
updateLabel(zoom, latlonRect, downloadText, template, seekBar.getProgress());
|
||||
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
updateLabel(zoom, latlonRect, downloadText, template, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
builder.setPositiveButton(R.string.download_files, new DialogInterface.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
run(zoom, seekBar.getProgress(), latlonRect, mapSource);
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.default_buttons_cancel, null);
|
||||
builder.setView(view);
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private volatile boolean cancel = false;
|
||||
|
||||
public void run(final int zoom, final int progress, final RectF latlonRect, final ITileSource map){
|
||||
cancel = false;
|
||||
int numberTiles = 0;
|
||||
for (int z = zoom; z <= progress + zoom; z++) {
|
||||
int x1 = (int) MapUtils.getTileNumberX(z, latlonRect.left);
|
||||
int x2 = (int) MapUtils.getTileNumberX(z, latlonRect.right);
|
||||
int y1 = (int) MapUtils.getTileNumberY(z, latlonRect.top);
|
||||
int y2 = (int) MapUtils.getTileNumberY(z, latlonRect.bottom);
|
||||
numberTiles += (x2 - x1 + 1) * (y2 - y1 + 1);
|
||||
}
|
||||
final ProgressDialog progressDlg = new ProgressDialog(ctx);
|
||||
progressDlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
progressDlg.setMessage(ctx.getString(R.string.downloading));
|
||||
progressDlg.setCancelable(true);
|
||||
progressDlg.setMax(numberTiles);
|
||||
progressDlg.setOnCancelListener(new DialogInterface.OnCancelListener(){
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
cancel = true;
|
||||
}
|
||||
});
|
||||
|
||||
final MapTileDownloader instance = MapTileDownloader.getInstance();
|
||||
|
||||
final ArrayList<IMapDownloaderCallback> previousCallbacks =
|
||||
new ArrayList<IMapDownloaderCallback>(instance.getDownloaderCallbacks());
|
||||
instance.getDownloaderCallbacks().clear();
|
||||
instance.addDownloaderCallback(new IMapDownloaderCallback(){
|
||||
@Override
|
||||
public void tileDownloaded(DownloadRequest request) {
|
||||
progressDlg.setProgress(progressDlg.getProgress() + 1);
|
||||
}
|
||||
});
|
||||
|
||||
Runnable r = new Runnable(){
|
||||
@Override
|
||||
public void run() {
|
||||
int requests = 0;
|
||||
int limitRequests = 50;
|
||||
try {
|
||||
ResourceManager rm = app.getResourceManager();
|
||||
for (int z = zoom; z <= zoom + progress && !cancel; z++) {
|
||||
int x1 = (int) MapUtils.getTileNumberX(z, latlonRect.left);
|
||||
int x2 = (int) MapUtils.getTileNumberX(z, latlonRect.right);
|
||||
int y1 = (int) MapUtils.getTileNumberY(z, latlonRect.top);
|
||||
int y2 = (int) MapUtils.getTileNumberY(z, latlonRect.bottom);
|
||||
for (int x = x1; x <= x2 && !cancel; x++) {
|
||||
for (int y = y1; y <= y2 && !cancel; y++) {
|
||||
String tileId = rm.calculateTileId(map, x, y, z);
|
||||
if (rm.tileExistOnFileSystem(tileId, map, x, y, z)) {
|
||||
progressDlg.setProgress(progressDlg.getProgress() + 1);
|
||||
} else {
|
||||
rm.getTileImageForMapSync(tileId, map, x, y, z, true);
|
||||
requests++;
|
||||
}
|
||||
if (!cancel) {
|
||||
if (requests >= limitRequests) {
|
||||
requests = 0;
|
||||
|
||||
while (instance.isSomethingBeingDownloaded()) {
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if(cancel){
|
||||
instance.refuseAllPreviousRequests();
|
||||
} else {
|
||||
while (instance.isSomethingBeingDownloaded()) {
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
mapView.refreshMap();
|
||||
} catch (Exception e) {
|
||||
log.error("Exception while downloading tiles ", e); //$NON-NLS-1$
|
||||
instance.refuseAllPreviousRequests();
|
||||
} finally {
|
||||
instance.getDownloaderCallbacks().clear();
|
||||
instance.getDownloaderCallbacks().addAll(previousCallbacks);
|
||||
app.getResourceManager().reloadTilesFromFS();
|
||||
}
|
||||
progressDlg.dismiss();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
new Thread(r, "Downloading tiles").start(); //$NON-NLS-1$
|
||||
progressDlg.show();
|
||||
}
|
||||
|
||||
|
||||
private void updateLabel(final int zoom, final RectF latlonRect, final TextView downloadText, final String template, int progress) {
|
||||
int numberTiles = 0;
|
||||
for (int z = zoom; z <= progress + zoom; z++) {
|
||||
int x1 = (int) MapUtils.getTileNumberX(z, latlonRect.left);
|
||||
int x2 = (int) MapUtils.getTileNumberX(z, latlonRect.right);
|
||||
int y1 = (int) MapUtils.getTileNumberY(z, latlonRect.top);
|
||||
int y2 = (int) MapUtils.getTileNumberY(z, latlonRect.bottom);
|
||||
numberTiles += (x2 - x1 + 1) * (y2 - y1 + 1);
|
||||
}
|
||||
downloadText.setText(MessageFormat.format(template, (progress + zoom)+"", //$NON-NLS-1$
|
||||
numberTiles, (double)numberTiles*12/1000));
|
||||
}
|
||||
}
|
|
@ -88,9 +88,9 @@ public class MainMenuActivity extends Activity {
|
|||
}
|
||||
}
|
||||
|
||||
public Animation getAnimation(boolean left){
|
||||
Animation anim = new TranslateAnimation(TranslateAnimation.RELATIVE_TO_SELF, left ? -1 : 1,
|
||||
TranslateAnimation.RELATIVE_TO_SELF, 0, TranslateAnimation.RELATIVE_TO_SELF, 0, TranslateAnimation.RELATIVE_TO_SELF, 0);
|
||||
public Animation getAnimation(int left, int top){
|
||||
Animation anim = new TranslateAnimation(TranslateAnimation.RELATIVE_TO_SELF, left,
|
||||
TranslateAnimation.RELATIVE_TO_SELF, 0, TranslateAnimation.RELATIVE_TO_SELF, top, TranslateAnimation.RELATIVE_TO_SELF, 0);
|
||||
anim.setDuration(700);
|
||||
anim.setInterpolator(new AccelerateInterpolator());
|
||||
return anim;
|
||||
|
@ -102,16 +102,18 @@ public class MainMenuActivity extends Activity {
|
|||
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
setContentView(R.layout.menu);
|
||||
View head = (View) findViewById(R.id.Headliner);
|
||||
head.startAnimation(getAnimation(0, -1));
|
||||
|
||||
View leftview = (View) findViewById(R.id.MapButton);
|
||||
leftview.startAnimation(getAnimation(true));
|
||||
leftview.startAnimation(getAnimation(-1, 0));
|
||||
leftview = (View) findViewById(R.id.FavoritesButton);
|
||||
leftview.startAnimation(getAnimation(true));
|
||||
leftview.startAnimation(getAnimation(-1, 0));
|
||||
|
||||
View rightview = (View) findViewById(R.id.SettingsButton);
|
||||
rightview.startAnimation(getAnimation(false));
|
||||
rightview.startAnimation(getAnimation(1, 0));
|
||||
rightview = (View) findViewById(R.id.SearchButton);
|
||||
rightview.startAnimation(getAnimation(false));
|
||||
rightview.startAnimation(getAnimation(1, 0));
|
||||
|
||||
final TextView textView = (TextView) findViewById(R.id.TextVersion);
|
||||
textView.setText(Version.APP_VERSION+ " "+ Version.APP_DESCRIPTION); //$NON-NLS-1$
|
||||
|
|
|
@ -1554,6 +1554,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
actions.add(resources.getString(R.string.context_menu_item_create_poi));
|
||||
actions.add(resources.getString(R.string.context_menu_item_open_bug));
|
||||
actions.add(resources.getString(R.string.context_menu_item_update_map));
|
||||
actions.add(resources.getString(R.string.context_menu_item_download_map));
|
||||
builder.setItems(actions.toArray(new String[actions.size()]), new DialogInterface.OnClickListener(){
|
||||
|
||||
@Override
|
||||
|
@ -1587,6 +1588,10 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
osmBugsLayer.openBug(MapActivity.this, getLayoutInflater(), mapView, latitude, longitude);
|
||||
} else if(which == 7){
|
||||
reloadTile(mapView.getZoom(), latitude, longitude);
|
||||
} else if(which == 8){
|
||||
DownloadTilesDialog dlg = new DownloadTilesDialog(MapActivity.this,
|
||||
(OsmandApplication) getApplication(), mapView);
|
||||
dlg.openDialog();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue