- extract App into separate project, make VectorTileMap a library project

- added minimum MapActivity example
This commit is contained in:
Hannes Janetzek
2012-10-28 17:28:24 +01:00
parent ab5962d56c
commit 5916f1be5e
120 changed files with 0 additions and 7694 deletions

View File

@@ -1,38 +0,0 @@
/*
* Copyright 2012 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app;
import org.oscim.view.MapView;
import android.app.Application;
import android.content.res.Resources;
// see http://androidcookbook.com : Android's Application Object as a "Singleton"
public class App extends Application {
public static final String TAG = "TileMap";
static MapView map;
static POISearch poiSearch;
static Resources res;
@Override
public void onCreate() {
super.onCreate();
res = getResources();
// Log.d("...", ">>>>>>>> INIT <<<<<<<");
// sInstance = this;
// sInstance.initializeInstance();
}
}

View File

@@ -1,65 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app;
import java.text.DecimalFormat;
import android.content.res.Resources;
final class FileUtils {
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.00 ");
private static final double ONE_GIGABYTE = 1000000000;
private static final double ONE_KILOBYTE = 1000;
private static final double ONE_MEGABYTE = 1000000;
/**
* Formats the given file size as a human readable string, using SI prefixes.
*
* @param fileSize
* the file size to be formatted.
* @param resources
* a reference to the application resources.
* @return a human readable file size.
* @throws IllegalArgumentException
* if the given file size is negative.
*/
static String formatFileSize(long fileSize, Resources resources) {
if (fileSize < 0) {
throw new IllegalArgumentException("invalid file size: " + fileSize);
} else if (fileSize < 1000) {
if (fileSize == 1) {
// singular
return "1 " + resources.getString(R.string.file_size_byte);
}
// plural, including zero
return fileSize + " " + resources.getString(R.string.file_size_bytes);
} else {
if (fileSize < ONE_MEGABYTE) {
return DECIMAL_FORMAT.format(fileSize / ONE_KILOBYTE)
+ resources.getString(R.string.file_size_kb);
} else if (fileSize < ONE_GIGABYTE) {
return DECIMAL_FORMAT.format(fileSize / ONE_MEGABYTE)
+ resources.getString(R.string.file_size_mb);
}
return DECIMAL_FORMAT.format(fileSize / ONE_GIGABYTE)
+ resources.getString(R.string.file_size_gb);
}
}
private FileUtils() {
throw new IllegalStateException();
}
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app;
import android.app.Activity;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.WindowManager;
import android.webkit.WebView;
/**
* Simple activity to display the info web page from the assets folder.
*/
public class InfoView extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webView = new WebView(this);
webView.loadUrl("file:///android_asset/info.xml");
setContentView(webView);
}
@Override
protected void onResume() {
super.onResume();
// check if the full screen mode should be activated
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen", false)) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
}
}
}

View File

@@ -1,113 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2012 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app;
import org.oscim.core.GeoPoint;
import org.oscim.core.MapPosition;
import org.oscim.view.MapView;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.TextView;
public class LocationDialog {
void prepareDialog(MapView mapView, final Dialog dialog) {
EditText editText = (EditText) dialog.findViewById(R.id.latitude);
GeoPoint mapCenter = mapView.getMapPosition().getMapCenter();
editText.setText(Double.toString(mapCenter.getLatitude()));
editText = (EditText) dialog.findViewById(R.id.longitude);
editText.setText(Double.toString(mapCenter.getLongitude()));
SeekBar zoomlevel = (SeekBar) dialog.findViewById(R.id.zoomLevel);
zoomlevel.setMax(20); // FIXME
// map.getMapGenerator().getZoomLevelMax());
zoomlevel.setProgress(mapView.getMapPosition().getZoomLevel());
final TextView textView = (TextView) dialog.findViewById(R.id.zoomlevelValue);
textView.setText(String.valueOf(zoomlevel.getProgress()));
zoomlevel.setOnSeekBarChangeListener(new SeekBarChangeListener(textView));
}
Dialog createDialog(final TileMap map) {
AlertDialog.Builder builder = new AlertDialog.Builder(map);
builder.setIcon(android.R.drawable.ic_menu_mylocation);
builder.setTitle(R.string.menu_position_enter_coordinates);
LayoutInflater factory = LayoutInflater.from(map);
final View view = factory.inflate(R.layout.dialog_enter_coordinates, null);
builder.setView(view);
builder.setPositiveButton(R.string.go_to_position,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// disable GPS follow mode if it is enabled
map.mLocation.disableSnapToLocation(true);
// set the map center and zoom level
EditText latitudeView = (EditText) view
.findViewById(R.id.latitude);
EditText longitudeView = (EditText) view
.findViewById(R.id.longitude);
double latitude = Double.parseDouble(latitudeView.getText()
.toString());
double longitude = Double.parseDouble(longitudeView.getText()
.toString());
SeekBar zoomLevelView = (SeekBar) view
.findViewById(R.id.zoomLevel);
byte zoom = (byte) (zoomLevelView.getProgress());
MapPosition mapPosition = new MapPosition(latitude,
longitude, zoom, 1, 0);
map.map.setMapCenter(mapPosition);
}
});
builder.setNegativeButton(R.string.cancel, null);
return builder.create();
}
class SeekBarChangeListener implements SeekBar.OnSeekBarChangeListener {
private final TextView textView;
SeekBarChangeListener(TextView textView) {
this.textView = textView;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
this.textView.setText(String.valueOf(progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// do nothing
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// do nothing
}
}
}

View File

@@ -1,258 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app;
import org.oscim.core.GeoPoint;
import org.oscim.core.MapPosition;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ToggleButton;
public class LocationHandler {
private static final int DIALOG_LOCATION_PROVIDER_DISABLED = 2;
private MyLocationListener mLocationListener;
private LocationManager mLocationManager;
private boolean mShowMyLocation;
private ToggleButton mSnapToLocationView;
private boolean mSnapToLocation;
/* package */final TileMap mTileMap;
LocationHandler(TileMap tileMap) {
mTileMap = tileMap;
mLocationManager = (LocationManager) tileMap
.getSystemService(Context.LOCATION_SERVICE);
mLocationListener = new MyLocationListener();
mSnapToLocationView = (ToggleButton) tileMap
.findViewById(R.id.snapToLocationView);
mSnapToLocationView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (isSnapToLocationEnabled()) {
disableSnapToLocation(true);
} else {
enableSnapToLocation(true);
}
}
});
}
boolean enableShowMyLocation(boolean centerAtFirstFix) {
Log.d("TileMap", "enableShowMyLocation " + mShowMyLocation);
gotoLastKnownPosition();
if (!mShowMyLocation) {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
String bestProvider = mLocationManager.getBestProvider(criteria, true);
if (bestProvider == null) {
mTileMap.showDialog(DIALOG_LOCATION_PROVIDER_DISABLED);
return false;
}
mShowMyLocation = true;
Log.d("TileMap", "enableShowMyLocation " + mShowMyLocation);
mLocationListener.setFirstCenter(centerAtFirstFix);
mLocationManager.requestLocationUpdates(bestProvider, 1000, 0,
mLocationListener);
mSnapToLocationView.setVisibility(View.VISIBLE);
return true;
}
return false;
}
void gotoLastKnownPosition() {
Location currentLocation;
Location bestLocation = null;
for (String provider : mLocationManager.getProviders(true)) {
currentLocation = mLocationManager.getLastKnownLocation(provider);
if (currentLocation == null)
continue;
if (bestLocation == null
|| currentLocation.getAccuracy() < bestLocation.getAccuracy()) {
bestLocation = currentLocation;
}
}
if (bestLocation != null) {
byte zoom = mTileMap.map.getMapPosition().getZoomLevel();
if (zoom < 12)
zoom = (byte) 12;
MapPosition mapPosition = new MapPosition(bestLocation.getLatitude(),
bestLocation.getLongitude(), zoom, 1, 0);
mTileMap.map.setMapCenter(mapPosition);
} else {
mTileMap.showToastOnUiThread(mTileMap
.getString(R.string.error_last_location_unknown));
}
}
/**
* Disables the "show my location" mode.
*
* @return ...
*/
boolean disableShowMyLocation() {
if (mShowMyLocation) {
mShowMyLocation = false;
disableSnapToLocation(false);
mLocationManager.removeUpdates(mLocationListener);
// if (circleOverlay != null) {
// mapView.getOverlays().remove(circleOverlay);
// mapView.getOverlays().remove(itemizedOverlay);
// circleOverlay = null;
// itemizedOverlay = null;
// }
mSnapToLocationView.setVisibility(View.GONE);
return true;
}
return false;
}
/**
* Returns the status of the "show my location" mode.
*
* @return true if the "show my location" mode is enabled, false otherwise.
*/
boolean isShowMyLocationEnabled() {
return mShowMyLocation;
}
/**
* Disables the "snap to location" mode.
*
* @param showToast
* defines whether a toast message is displayed or not.
*/
void disableSnapToLocation(boolean showToast) {
if (mSnapToLocation) {
mSnapToLocation = false;
mSnapToLocationView.setChecked(false);
mTileMap.map.setClickable(true);
if (showToast) {
mTileMap.showToastOnUiThread(mTileMap
.getString(R.string.snap_to_location_disabled));
}
}
}
/**
* Enables the "snap to location" mode.
*
* @param showToast
* defines whether a toast message is displayed or not.
*/
void enableSnapToLocation(boolean showToast) {
if (!mSnapToLocation) {
mSnapToLocation = true;
mTileMap.map.setClickable(false);
if (showToast) {
mTileMap.showToastOnUiThread(mTileMap
.getString(R.string.snap_to_location_enabled));
}
}
}
/**
* Returns the status of the "snap to location" mode.
*
* @return true if the "snap to location" mode is enabled, false otherwise.
*/
boolean isSnapToLocationEnabled() {
return mSnapToLocation;
}
class MyLocationListener implements LocationListener {
private boolean mSetCenter;
@Override
public void onLocationChanged(Location location) {
Log.d("LocationListener", "onLocationChanged, "
+ " lon:" + location.getLongitude()
+ " lat:" + location.getLatitude());
if (!isShowMyLocationEnabled()) {
return;
}
GeoPoint point = new GeoPoint(location.getLatitude(), location.getLongitude());
// this.advancedMapViewer.overlayCircle.setCircleData(point, location.getAccuracy());
// this.advancedMapViewer.overlayItem.setPoint(point);
// this.advancedMapViewer.circleOverlay.requestRedraw();
// this.advancedMapViewer.itemizedOverlay.requestRedraw();
if (mSetCenter || isSnapToLocationEnabled()) {
mSetCenter = false;
mTileMap.map.setCenter(point);
}
}
@Override
public void onProviderDisabled(String provider) {
// do nothing
}
@Override
public void onProviderEnabled(String provider) {
// do nothing
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// do nothing
}
boolean isFirstCenter() {
return mSetCenter;
}
void setFirstCenter(boolean center) {
mSetCenter = center;
}
}
}

View File

@@ -1,96 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app;
public class MapInfoDialog {
//onCreate
// else if (id == DIALOG_INFO_MAP_FILE) {
// builder.setIcon(android.R.drawable.ic_menu_info_details);
// builder.setTitle(R.string.menu_info_map_file);
// LayoutInflater factory = LayoutInflater.from(this);
// builder.setView(factory.inflate(R.layout.dialog_info_map_file, null));
// builder.setPositiveButton(R.string.ok, null);
// return builder.create();
//onPrepare
// } else if (id == DIALOG_INFO_MAP_FILE) {
// MapInfo mapInfo = map.getMapDatabase().getMapInfo();
//
// TextView textView = (TextView)
// dialog.findViewById(R.id.infoMapFileViewName);
// textView.setText(map.getMapFile());
//
// textView = (TextView)
// dialog.findViewById(R.id.infoMapFileViewSize);
// textView.setText(FileUtils.formatFileSize(mapInfo.fileSize,
// getResources()));
//
// textView = (TextView)
// dialog.findViewById(R.id.infoMapFileViewVersion);
// textView.setText(String.valueOf(mapInfo.fileVersion));
//
// // textView = (TextView)
// dialog.findViewById(R.id.infoMapFileViewDebug);
// // if (mapFileInfo.debugFile) {
// // textView.setText(R.string.info_map_file_debug_yes);
// // } else {
// // textView.setText(R.string.info_map_file_debug_no);
// // }
//
// textView = (TextView)
// dialog.findViewById(R.id.infoMapFileViewDate);
// Date date = new Date(mapInfo.mapDate);
// textView.setText(DateFormat.getDateTimeInstance().format(date));
//
// textView = (TextView)
// dialog.findViewById(R.id.infoMapFileViewArea);
// BoundingBox boundingBox = mapInfo.boundingBox;
// textView.setText(boundingBox.getMinLatitude() + ", "
// + boundingBox.getMinLongitude() + " - \n"
// + boundingBox.getMaxLatitude() + ", " +
// boundingBox.getMaxLongitude());
//
// textView = (TextView)
// dialog.findViewById(R.id.infoMapFileViewStartPosition);
// GeoPoint startPosition = mapInfo.startPosition;
// if (startPosition == null) {
// textView.setText(null);
// } else {
// textView.setText(startPosition.getLatitude() + ", "
// + startPosition.getLongitude());
// }
//
// textView = (TextView)
// dialog.findViewById(R.id.infoMapFileViewStartZoomLevel);
// Byte startZoomLevel = mapInfo.startZoomLevel;
// if (startZoomLevel == null) {
// textView.setText(null);
// } else {
// textView.setText(startZoomLevel.toString());
// }
//
// textView = (TextView) dialog
// .findViewById(R.id.infoMapFileViewLanguagePreference);
// textView.setText(mapInfo.languagePreference);
//
// textView = (TextView)
// dialog.findViewById(R.id.infoMapFileViewComment);
// textView.setText(mapInfo.comment);
//
// textView = (TextView)
// dialog.findViewById(R.id.infoMapFileViewCreatedBy);
// textView.setText(mapInfo.createdBy);
}

View File

@@ -1,261 +0,0 @@
/*
* Copyright 2012 osmdroidbonuspack: M.Kergall
* Copyright 2012 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app;
import java.util.ArrayList;
import org.osmdroid.location.POI;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
/**
* Activity showing POIs as a list.
* @author M.Kergall
*/
public class POIActivity extends Activity {
AutoCompleteTextView poiTagText;
POIAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.items_list);
// TextView title = (TextView) findViewById(R.id.title);
// title.setText("Points of Interest");
ListView list = (ListView) findViewById(R.id.items);
Intent myIntent = getIntent();
final ArrayList<POI> pois = myIntent.getParcelableArrayListExtra("POI");
final int currentNodeId = myIntent.getIntExtra("ID", -1);
POIAdapter adapter = new POIAdapter(this, pois);
mAdapter = adapter;
// Log.d(App.TAG, "got POIs:" + (pois == null ? pois : pois.size()));
list.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View view, int position, long index) {
Intent intent = new Intent();
intent.putExtra("ID", position);
setResult(RESULT_OK, intent);
finish();
}
});
list.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
Log.d(App.TAG, "context menu created 2");
}
});
list.setAdapter(adapter);
list.setSelection(currentNodeId);
// POI search interface:
String[] poiTags = getResources().getStringArray(R.array.poi_tags);
poiTagText = (AutoCompleteTextView) findViewById(R.id.poiTag);
ArrayAdapter<String> textadapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, poiTags);
poiTagText.setAdapter(textadapter);
Button setPOITagButton = (Button) findViewById(R.id.buttonSetPOITag);
setPOITagButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Hide the soft keyboard:
InputMethodManager imm = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(poiTagText.getWindowToken(), 0);
//Start search:
App.poiSearch.getPOIAsync(poiTagText.getText().toString());
}
});
registerForContextMenu(list);
// only show keyboard when nothing in the list yet
if (pois == null || pois.size() == 0) {
poiTagText.postDelayed(new Runnable() {
@Override
public void run() {
InputMethodManager keyboard = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
keyboard.showSoftInput(poiTagText, 0);
}
}, 200);
}
}
@Override
protected void onNewIntent(Intent intent) {
Log.d(App.TAG, "NEW INTENT!!!!");
// from SearchableDictionary Example:
// Because this activity has set launchMode="singleTop", the system calls this method
// to deliver the intent if this activity is currently the foreground activity when
// invoked again (when the user executes a search from this activity, we don't create
// a new instance of this activity, so the system delivers the search intent here)
// handleIntent(intent);
final ArrayList<POI> pois = intent.getParcelableArrayListExtra("POI");
// final int currentNodeId = intent.getIntExtra("ID", -1);
// POIAdapter adapter = new POIAdapter(this, pois);
mAdapter.setPOI(pois);
mAdapter.notifyDataSetChanged();
}
// http://www.mikeplate.com/2010/01/21/show-a-context-menu-for-long-clicks-in-an-android-listview/
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
if (v.getId() == R.id.items) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
Log.d(App.TAG, "list context menu created " + info.position);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.poi_menu, menu);
}
super.onCreateContextMenu(menu, v, menuInfo);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
Log.d(App.TAG, "context menu item selected " + item.getItemId());
if (item.getItemId() == R.id.menu_link) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item
.getMenuInfo();
POI poi = (POI) mAdapter.getItem(info.position);
if (poi != null && poi.url != null) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(poi.url));
startActivity(i);
}
return true;
}
return super.onContextItemSelected(item);
}
}
class POIAdapter extends BaseAdapter implements OnClickListener {
private Context mContext;
private ArrayList<POI> mPois;
public POIAdapter(Context context, ArrayList<POI> pois) {
mContext = context;
mPois = pois;
}
public void setPOI(ArrayList<POI> pois) {
mPois = pois;
}
@Override
public int getCount() {
if (mPois == null)
return 0;
return mPois.size();
}
@Override
public Object getItem(int position) {
if (mPois == null)
return null;
return mPois.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
POI entry = (POI) getItem(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.item_layout, null);
} else {
}
TextView tvTitle = (TextView) convertView.findViewById(R.id.title);
tvTitle.setText((entry.url == null ? "" : "[link] ") + entry.type);
TextView tvDetails = (TextView) convertView.findViewById(R.id.details);
tvDetails.setText(entry.description);
ImageView iv = (ImageView) convertView.findViewById(R.id.thumbnail);
//ivManeuver.setImageBitmap(entry.mThumbnail);
// iv.getT
// entry.fetchThumbnailOnThread(iv);
entry.fetchThumbnail(iv);
return convertView;
}
@Override
public void onClick(View arg0) {
Log.d(App.TAG, "click" + arg0.getId());
//nothing to do.
}
}

View File

@@ -1,197 +0,0 @@
/*
* Copyright 2012 osmdroid: M.Kergall
* Copyright 2012 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app;
import java.util.ArrayList;
import org.oscim.core.BoundingBox;
import org.oscim.overlay.OverlayItem;
import org.osmdroid.location.FlickrPOIProvider;
import org.osmdroid.location.GeoNamesPOIProvider;
import org.osmdroid.location.NominatimPOIProvider;
import org.osmdroid.location.POI;
import org.osmdroid.location.PicasaPOIProvider;
import org.osmdroid.overlays.ExtendedOverlayItem;
import org.osmdroid.overlays.ItemizedOverlayWithBubble;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.AutoCompleteTextView;
import android.widget.Toast;
public class POISearch {
ArrayList<POI> mPOIs;
ItemizedOverlayWithBubble<ExtendedOverlayItem> poiMarkers;
AutoCompleteTextView poiTagText;
final TileMap tileMap;
POISearch(TileMap tileMap) {
this.tileMap = tileMap;
//POI markers:
final ArrayList<ExtendedOverlayItem> poiItems = new ArrayList<ExtendedOverlayItem>();
poiMarkers = new ItemizedOverlayWithBubble<ExtendedOverlayItem>(tileMap.map, tileMap,
poiItems, null); //new POIInfoWindow(map));
tileMap.map.getOverlays().add(poiMarkers);
// if (savedInstanceState != null) {
// mPOIs = savedInstanceState.getParcelableArrayList("poi");
// updateUIWithPOI(mPOIs);
// }
}
// void init() {
//
// }
class POITask extends AsyncTask<Object, Void, ArrayList<POI>> {
String mTag;
@Override
protected ArrayList<POI> doInBackground(Object... params) {
mTag = (String) params[0];
if (mTag == null || mTag.equals("")) {
return null;
} else if (mTag.equals("wikipedia")) {
GeoNamesPOIProvider poiProvider = new GeoNamesPOIProvider("mkergall");
//ArrayList<POI> pois = poiProvider.getPOICloseTo(point, 30, 20.0);
//Get POI inside the bounding box of the current map view:
BoundingBox bb = App.map.getBoundingBox();
ArrayList<POI> pois = poiProvider.getPOIInside(bb, 30);
return pois;
} else if (mTag.equals("flickr")) {
FlickrPOIProvider poiProvider = new FlickrPOIProvider(
"c39be46304a6c6efda8bc066c185cd7e");
BoundingBox bb = App.map.getBoundingBox();
ArrayList<POI> pois = poiProvider.getPOIInside(bb, 20);
return pois;
} else if (mTag.startsWith("picasa")) {
PicasaPOIProvider poiProvider = new PicasaPOIProvider(null);
BoundingBox bb = App.map.getBoundingBox();
String q = mTag.substring("picasa".length());
ArrayList<POI> pois = poiProvider.getPOIInside(bb, 20, q);
return pois;
}
else {
NominatimPOIProvider poiProvider = new NominatimPOIProvider();
// poiProvider.setService(NominatimPOIProvider.MAPQUEST_POI_SERVICE);
poiProvider.setService(NominatimPOIProvider.NOMINATIM_POI_SERVICE);
ArrayList<POI> pois;
// if (destinationPoint == null) {
BoundingBox bb = App.map.getBoundingBox();
pois = poiProvider.getPOIInside(bb, mTag, 100);
// } else {
// pois = poiProvider.getPOIAlong(mRoad.getRouteLow(), mTag, 100, 2.0);
// }
return pois;
}
}
@Override
protected void onPostExecute(ArrayList<POI> pois) {
mPOIs = pois;
if (mTag.equals("")) {
//no search, no message
} else if (mPOIs == null) {
Toast.makeText(tileMap.getApplicationContext(),
"Technical issue when getting " + mTag + " POI.", Toast.LENGTH_LONG)
.show();
} else {
Toast.makeText(tileMap.getApplicationContext(),
"" + mPOIs.size() + " " + mTag + " entries found",
Toast.LENGTH_LONG).show();
// if (mTag.equals("flickr") || mTag.startsWith("picasa") || mTag.equals("wikipedia"))
// startAsyncThumbnailsLoading(mPOIs);
}
updateUIWithPOI(mPOIs);
}
}
void updateUIWithPOI(ArrayList<POI> pois) {
if (pois != null) {
for (POI poi : pois) {
int end = 0, first = 0;
String desc = null;
String name = poi.description;
if (poi.serviceId == POI.POI_SERVICE_NOMINATIM) {
if (name != null) {
// FIXME or nominatim...
// String name = "";
for (int i = 0; i < 3; i++) {
int pos = poi.description.indexOf(',', end);
if (pos > 0) {
if (i == 0) {
name = poi.description.substring(0, pos);
first = pos + 2;
}
end = pos + 1;
}
}
if (end > 0)
desc = poi.description.substring(first, end - 1);
else
desc = poi.description;
}
}
ExtendedOverlayItem poiMarker = new ExtendedOverlayItem(
poi.type + (name == null ? "" : ": " + name), desc, poi.location);
Drawable marker = null;
if (poi.serviceId == POI.POI_SERVICE_NOMINATIM) {
marker = App.res.getDrawable(R.drawable.marker_poi_default);
} else if (poi.serviceId == POI.POI_SERVICE_GEONAMES_WIKIPEDIA) {
if (poi.rank < 90)
marker = App.res.getDrawable(R.drawable.marker_poi_wikipedia_16);
else
marker = App.res.getDrawable(R.drawable.marker_poi_wikipedia_32);
} else if (poi.serviceId == POI.POI_SERVICE_FLICKR) {
marker = App.res.getDrawable(R.drawable.marker_poi_flickr);
} else if (poi.serviceId == POI.POI_SERVICE_PICASA) {
marker = App.res.getDrawable(R.drawable.marker_poi_picasa_24);
poiMarker.setSubDescription(poi.category);
}
poiMarker.setMarker(marker);
poiMarker.setMarkerHotspot(OverlayItem.HotspotPlace.CENTER);
//thumbnail loading moved in POIInfoWindow.onOpen for better performances.
poiMarker.setRelatedObject(poi);
poiMarkers.addItem(poiMarker);
}
Log.d(App.TAG, "SEND INTENT");
Intent intent = new Intent(tileMap.getApplicationContext(), POIActivity.class);
intent.putParcelableArrayListExtra("POI", mPOIs);
intent.putExtra("ID", poiMarkers.getBubbledItemId());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
tileMap.startActivityForResult(intent, TileMap.POIS_REQUEST);
}
App.map.redrawMap();
}
void getPOIAsync(String tag) {
poiMarkers.removeAllItems();
new POITask().execute(tag);
}
}

View File

@@ -1,403 +0,0 @@
/*
* Copyright 2012 osmdroid: M.Kergall
* Copyright 2012 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.oscim.core.GeoPoint;
import org.oscim.overlay.Overlay;
import org.oscim.overlay.OverlayItem;
import org.oscim.overlay.PathOverlay;
import org.oscim.view.MapView;
import org.osmdroid.location.GeocoderNominatim;
import org.osmdroid.overlays.DefaultInfoWindow;
import org.osmdroid.overlays.ExtendedOverlayItem;
import org.osmdroid.overlays.ItemizedOverlayWithBubble;
import org.osmdroid.overlays.MapEventsOverlay;
import org.osmdroid.overlays.MapEventsReceiver;
import org.osmdroid.routing.OSRMRoadManager;
import org.osmdroid.routing.Road;
import org.osmdroid.routing.RoadManager;
import org.osmdroid.routing.RoadNode;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.os.AsyncTask;
import android.util.Log;
import android.view.MenuItem;
import android.widget.Toast;
public class RouteSearch implements MapEventsReceiver {
protected Road mRoad;
protected PathOverlay mRoadOverlay;
protected ItemizedOverlayWithBubble<ExtendedOverlayItem> mRoadNodeMarkers;
protected GeoPoint startPoint, destinationPoint;
protected ArrayList<GeoPoint> viaPoints;
protected static int START_INDEX = -2, DEST_INDEX = -1;
protected ExtendedOverlayItem markerStart, markerDestination;
protected ItemizedOverlayWithBubble<ExtendedOverlayItem> itineraryMarkers;
private final TileMap tileMap;
RouteSearch(TileMap tileMap) {
// keep context and mapview reference
this.tileMap = tileMap;
//To use MapEventsReceiver methods, we add a MapEventsOverlay:
MapEventsOverlay overlay = new MapEventsOverlay(tileMap, this);
tileMap.map.getOverlays().add(overlay);
// if (savedInstanceState == null) {
// Location l = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
// if (l != null) {
// startPoint = new GeoPoint(l.getLatitude(), l.getLongitude());
// } else {
// //we put a hard-coded start
startPoint = new GeoPoint(53.067221, 8.78767);
// }
destinationPoint = null;
viaPoints = new ArrayList<GeoPoint>();
// mapController.setZoom(9);
// mapController.setCenter(startPoint);
// }
// Itinerary markers:
final ArrayList<ExtendedOverlayItem> waypointsItems = new ArrayList<ExtendedOverlayItem>();
itineraryMarkers = new ItemizedOverlayWithBubble<ExtendedOverlayItem>(tileMap.map, tileMap,
waypointsItems, new ViaPointInfoWindow(R.layout.itinerary_bubble, tileMap.map));
tileMap.map.getOverlays().add(itineraryMarkers);
updateUIWithItineraryMarkers();
//Route and Directions
final ArrayList<ExtendedOverlayItem> roadItems = new ArrayList<ExtendedOverlayItem>();
mRoadNodeMarkers = new ItemizedOverlayWithBubble<ExtendedOverlayItem>(tileMap, roadItems,
tileMap.map);
tileMap.map.getOverlays().add(mRoadNodeMarkers);
// if (savedInstanceState != null) {
// mRoad = savedInstanceState.getParcelable("road");
// updateUIWithRoad(mRoad);
// }
}
//------------- Geocoding and Reverse Geocoding
/**
* Reverse Geocoding
* @param p
* ...
* @return ...
*/
public String getAddress(GeoPoint p) {
GeocoderNominatim geocoder = new GeocoderNominatim(tileMap);
String theAddress;
try {
double dLatitude = p.getLatitude();
double dLongitude = p.getLongitude();
List<Address> addresses = geocoder.getFromLocation(dLatitude, dLongitude, 1);
StringBuilder sb = new StringBuilder();
if (addresses.size() > 0) {
Address address = addresses.get(0);
int n = address.getMaxAddressLineIndex();
for (int i = 0; i <= n; i++) {
if (i != 0)
sb.append(", ");
sb.append(address.getAddressLine(i));
}
theAddress = new String(sb.toString());
} else {
theAddress = null;
}
} catch (IOException e) {
theAddress = null;
}
if (theAddress != null) {
return theAddress;
}
return "";
}
//Async task to reverse-geocode the marker position in a separate thread:
class GeocodingTask extends AsyncTask<Object, Void, String> {
ExtendedOverlayItem marker;
@Override
protected String doInBackground(Object... params) {
marker = (ExtendedOverlayItem) params[0];
return getAddress(marker.getPoint());
}
@Override
protected void onPostExecute(String result) {
marker.setDescription(result);
//itineraryMarkers.showBubbleOnItem(???, map); //open bubble on the item
}
}
//------------ Itinerary markers
/* add (or replace) an item in markerOverlays. p position. */
public ExtendedOverlayItem putMarkerItem(ExtendedOverlayItem item, GeoPoint p, int index,
int titleResId, int markerResId, int iconResId) {
if (item != null) {
itineraryMarkers.removeItem(item);
}
Drawable marker = App.res.getDrawable(markerResId);
String title = App.res.getString(titleResId);
ExtendedOverlayItem overlayItem = new ExtendedOverlayItem(title, "", p);
overlayItem.setMarkerHotspot(OverlayItem.HotspotPlace.BOTTOM_CENTER);
overlayItem.setMarker(marker);
if (iconResId != -1)
overlayItem.setImage(App.res.getDrawable(iconResId));
overlayItem.setRelatedObject(Integer.valueOf(index));
itineraryMarkers.addItem(overlayItem);
tileMap.map.redrawMap();
//map.invalidate();
//Start geocoding task to update the description of the marker with its address:
new GeocodingTask().execute(overlayItem);
return overlayItem;
}
public void addViaPoint(GeoPoint p) {
viaPoints.add(p);
putMarkerItem(null, p, viaPoints.size() - 1,
R.string.viapoint, R.drawable.marker_via, -1);
}
public void removePoint(int index) {
if (index == START_INDEX)
startPoint = null;
else if (index == DEST_INDEX)
destinationPoint = null;
else
viaPoints.remove(index);
getRoadAsync();
updateUIWithItineraryMarkers();
}
public void updateUIWithItineraryMarkers() {
itineraryMarkers.removeAllItems();
//Start marker:
if (startPoint != null) {
markerStart = putMarkerItem(null, startPoint, START_INDEX,
R.string.departure, R.drawable.marker_departure, -1);
}
//Via-points markers if any:
for (int index = 0; index < viaPoints.size(); index++) {
putMarkerItem(null, viaPoints.get(index), index,
R.string.viapoint, R.drawable.marker_via, -1);
}
//Destination marker if any:
if (destinationPoint != null) {
markerDestination = putMarkerItem(null, destinationPoint, DEST_INDEX,
R.string.destination,
R.drawable.marker_destination, -1);
}
}
//------------ Route and Directions
private void putRoadNodes(Road road) {
mRoadNodeMarkers.removeAllItems();
Drawable marker = App.res.getDrawable(R.drawable.marker_node);
int n = road.nodes.size();
// TypedArray iconIds = App.res.obtainTypedArray(R.array.direction_icons);
for (int i = 0; i < n; i++) {
RoadNode node = road.nodes.get(i);
String instructions = (node.instructions == null ? "" : node.instructions);
ExtendedOverlayItem nodeMarker = new ExtendedOverlayItem(
"Step " + (i + 1), instructions, node.location);
nodeMarker.setSubDescription(road.getLengthDurationText(node.length, node.duration));
nodeMarker.setMarkerHotspot(OverlayItem.HotspotPlace.CENTER);
nodeMarker.setMarker(marker);
// int iconId = iconIds.getResourceId(node.mManeuverType, R.drawable.ic_empty);
// if (iconId != R.drawable.ic_empty) {
// Drawable icon = App.res.getDrawable(iconId);
// nodeMarker.setImage(icon);
// }
mRoadNodeMarkers.addItem(nodeMarker);
}
}
void updateUIWithRoad(Road road) {
mRoadNodeMarkers.removeAllItems();
List<Overlay> mapOverlays = tileMap.map.getOverlays();
if (mRoadOverlay != null) {
mapOverlays.remove(mRoadOverlay);
}
if (road == null)
return;
if (road.status == Road.STATUS_DEFAULT)
Toast.makeText(tileMap, "We have a problem to get the route",
Toast.LENGTH_SHORT).show();
mRoadOverlay = RoadManager.buildRoadOverlay(tileMap.map, road, tileMap);
Overlay removedOverlay = mapOverlays.set(1, mRoadOverlay);
//we set the road overlay at the "bottom", just above the MapEventsOverlay,
//to avoid covering the other overlays.
mapOverlays.add(removedOverlay);
putRoadNodes(road);
tileMap.map.redrawMap();
// map.invalidate();
//Set route info in the text view:
// ((TextView) findViewById(R.id.routeInfo)).setText(road.getLengthDurationText(-1));
}
/**
* Async task to get the road in a separate thread.
*/
class UpdateRoadTask extends AsyncTask<WayPoints, Void, Road> {
@Override
protected Road doInBackground(WayPoints... wp) {
ArrayList<GeoPoint> waypoints = wp[0].waypoints;
//RoadManager roadManager = new GoogleRoadManager();
RoadManager roadManager = new OSRMRoadManager();
roadManager.addRequestOption("");
/* RoadManager roadManager = new MapQuestRoadManager(); Locale
* locale = Locale.getDefault();
* roadManager.addRequestOption("locale="+locale.getLanguage
* ()+"_"+locale.getCountry()); */
return roadManager.getRoad(waypoints);
}
@Override
protected void onPostExecute(Road result) {
mRoad = result;
updateUIWithRoad(result);
/// ??? getPOIAsync(poiTagText.getText().toString());
}
}
// Just to make JAVA shut up!
class WayPoints {
public ArrayList<GeoPoint> waypoints;
}
public void getRoadAsync() {
mRoad = null;
if (startPoint == null || destinationPoint == null) {
updateUIWithRoad(mRoad);
return;
}
ArrayList<GeoPoint> waypoints = new ArrayList<GeoPoint>(2);
waypoints.add(startPoint);
//add intermediate via points:
for (GeoPoint p : viaPoints) {
waypoints.add(p);
}
waypoints.add(destinationPoint);
WayPoints wp = new WayPoints();
wp.waypoints = waypoints;
new UpdateRoadTask().execute(wp);
}
//------------ MapEventsReceiver implementation
GeoPoint tempClickedGeoPoint; //any other way to pass the position to the menu ???
@Override
public boolean longPressHelper(GeoPoint p) {
Log.d(TileMap.TAG, ">>> got long press event " + p);
tempClickedGeoPoint = p;
//new GeoPoint((GeoPoint) p);
//menu is hooked on the "Search" button
// Button searchButton = (Button) findViewById(R.id.buttonSearch);
// tileMap.openContextMenu(searchButton);
tileMap.openContextMenu(tileMap.map);
return true;
}
@Override
public boolean singleTapUpHelper(GeoPoint p) {
Log.d(App.TAG, "single tap up");
mRoadNodeMarkers.hideBubble();
itineraryMarkers.hideBubble();
return false;
}
// ----------- context menu
boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_departure:
startPoint = tempClickedGeoPoint;
//new GeoPoint((GeoPoint) tempClickedGeoPoint);
markerStart = putMarkerItem(markerStart, startPoint, START_INDEX,
R.string.departure, R.drawable.marker_departure, -1);
getRoadAsync();
return true;
case R.id.menu_destination:
destinationPoint = tempClickedGeoPoint;
//new GeoPoint((GeoPoint) tempClickedGeoPoint);
markerDestination = putMarkerItem(markerDestination, destinationPoint, DEST_INDEX,
R.string.destination,
R.drawable.marker_destination, -1);
getRoadAsync();
return true;
case R.id.menu_viapoint:
GeoPoint viaPoint = tempClickedGeoPoint; //new GeoPoint((GeoPoint) tempClickedGeoPoint);
addViaPoint(viaPoint);
getRoadAsync();
return true;
default:
}
return false;
}
class ViaPointInfoWindow extends DefaultInfoWindow {
int mSelectedPoint;
public ViaPointInfoWindow(int layoutResId, MapView mapView) {
super(layoutResId, mapView);
// Button btnDelete = (Button)(mView.findViewById(R.id.bubble_delete));
// btnDelete.setOnClickListener(new View.OnClickListener() {
// public void onClick(View view) {
// //Call the removePoint method on MapActivity.
// //TODO: find a cleaner way to do that!
// MapActivity mapActivity = (MapActivity)view.getContext();
// mapActivity.removePoint(mSelectedPoint);
// close();
// }
// });
}
@Override
public void onOpen(ExtendedOverlayItem item) {
mSelectedPoint = ((Integer) item.getRelatedObject()).intValue();
super.onOpen(item);
}
}
}

View File

@@ -1,564 +0,0 @@
/* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2012 Hannes Janetzek
* Copyright 2012 osmdroidbonuspack: M.Kergall
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import org.oscim.app.filefilter.FilterByFileExtension;
import org.oscim.app.filefilter.ValidRenderTheme;
import org.oscim.app.filepicker.FilePicker;
import org.oscim.app.preferences.EditPreferences;
import org.oscim.database.MapDatabases;
import org.oscim.theme.InternalRenderTheme;
import org.oscim.utils.AndroidUtils;
import org.oscim.view.DebugSettings;
import org.oscim.view.MapActivity;
import org.oscim.view.MapView;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
public class TileMap extends MapActivity {
static final String TAG = TileMap.class.getSimpleName();
MapView map;
// private static final String BUNDLE_CENTER_AT_FIRST_FIX =
// "centerAtFirstFix";
private static final String BUNDLE_SHOW_MY_LOCATION = "showMyLocation";
private static final String BUNDLE_SNAP_TO_LOCATION = "snapToLocation";
private static final int DIALOG_ENTER_COORDINATES = 0;
// private static final int DIALOG_INFO_MAP_FILE = 1;
private static final int DIALOG_LOCATION_PROVIDER_DISABLED = 2;
// private static final FileFilter FILE_FILTER_EXTENSION_MAP =
// new FilterByFileExtension(".map");
private static final FileFilter FILE_FILTER_EXTENSION_XML =
new FilterByFileExtension(".xml");
// private static final int SELECT_MAP_FILE = 0;
// Intents
private static final int SELECT_RENDER_THEME_FILE = 1;
protected static final int POIS_REQUEST = 2;
LocationHandler mLocation;
private MapDatabases mMapDatabase;
private WakeLock mWakeLock;
private Menu mMenu = null;
POISearch mPoiSearch;
RouteSearch mRouteSearch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set up the layout views
setContentView(R.layout.activity_tilemap);
map = (MapView) findViewById(R.id.mapView);
App.map = map;
// configure the MapView and activate the zoomLevel buttons
map.setClickable(true);
// map.setBuiltInZoomControls(true);
map.setFocusable(true);
mLocation = new LocationHandler(this);
// get the pointers to different system services
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager
.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "AMV");
if (savedInstanceState != null) {
if (savedInstanceState.getBoolean(BUNDLE_SHOW_MY_LOCATION)) {
// enableShowMyLocation(savedInstanceState
// .getBoolean(BUNDLE_CENTER_AT_FIRST_FIX));
if (savedInstanceState.getBoolean(BUNDLE_SNAP_TO_LOCATION)) {
mLocation.enableSnapToLocation(false);
}
}
}
App.poiSearch = mPoiSearch = new POISearch(this);
registerForContextMenu(map);
mRouteSearch = new RouteSearch(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.options_menu, menu);
mMenu = menu;
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_info_about:
startActivity(new Intent(this, InfoView.class));
return true;
case R.id.menu_position:
return true;
case R.id.menu_rotation_enable:
map.enableRotation(true);
toggleMenuRotation();
return true;
case R.id.menu_rotation_disable:
map.enableRotation(false);
toggleMenuRotation();
return true;
case R.id.menu_compass_enable:
map.enableCompass(true);
toggleMenuRotation();
return true;
case R.id.menu_compass_disable:
map.enableCompass(false);
toggleMenuRotation();
return true;
case R.id.menu_position_my_location_enable:
toggleMenuItem(mMenu,
R.id.menu_position_my_location_enable,
R.id.menu_position_my_location_disable,
!mLocation.enableShowMyLocation(true));
return true;
case R.id.menu_position_my_location_disable:
toggleMenuItem(mMenu,
R.id.menu_position_my_location_enable,
R.id.menu_position_my_location_disable,
mLocation.disableShowMyLocation());
return true;
case R.id.menu_position_enter_coordinates:
showDialog(DIALOG_ENTER_COORDINATES);
return true;
case R.id.menu_preferences:
startActivity(new Intent(this, EditPreferences.class));
return true;
case R.id.menu_render_theme:
return true;
case R.id.menu_render_theme_osmarender:
map.setRenderTheme(InternalRenderTheme.OSMARENDER);
return true;
case R.id.menu_render_theme_tronrender:
map.setRenderTheme(InternalRenderTheme.TRONRENDER);
return true;
case R.id.menu_render_theme_select_file:
startRenderThemePicker();
return true;
// case R.id.menu_position_map_center:
// // disable GPS follow mode if it is enabled
// location.disableSnapToLocation(true);
//
// map.setCenter(map.getMapDatabase()
// .getMapInfo().mapCenter);
// return true;
// case R.id.menu_mapfile:
// startMapFilePicker();
// return true;
case R.id.menu_pois:
mPoiSearch.getPOIAsync("bar");
// Intent myIntent = new Intent(this, POIActivity.class);
// myIntent.putParcelableArrayListExtra("POI", mPOIs);
// // myIntent.putExtra("ID", poiMarkers.getBubbledItemId());
// startActivityForResult(myIntent, POIS_REQUEST);
return true;
case R.id.menu_poi_list:
Intent myIntent = new Intent(this, POIActivity.class);
myIntent.putParcelableArrayListExtra("POI", mPoiSearch.mPOIs);
myIntent.putExtra("ID", mPoiSearch.poiMarkers.getBubbledItemId());
startActivityForResult(myIntent, POIS_REQUEST);
return true;
default:
return false;
}
}
private void toggleMenuRotation() {
toggleMenuItem(mMenu,
R.id.menu_rotation_enable,
R.id.menu_rotation_disable,
!map.enableRotation);
toggleMenuItem(mMenu,
R.id.menu_compass_enable,
R.id.menu_compass_disable,
!map.enableCompass);
}
private static void toggleMenuItem(Menu menu, int id, int id2, boolean enable) {
menu.findItem(id).setVisible(enable);
menu.findItem(id).setEnabled(enable);
menu.findItem(id2).setVisible(!enable);
menu.findItem(id2).setEnabled(!enable);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (!isPreHoneyComb()) {
menu.clear();
onCreateOptionsMenu(menu);
}
toggleMenuItem(menu,
R.id.menu_position_my_location_enable,
R.id.menu_position_my_location_disable,
!mLocation.isShowMyLocationEnabled());
if (mMapDatabase == MapDatabases.MAP_READER) {
//menu.findItem(R.id.menu_mapfile).setVisible(true);
menu.findItem(R.id.menu_position_map_center).setVisible(true);
}
// else {
// menu.findItem(R.id.menu_mapfile).setVisible(false);
// menu.findItem(R.id.menu_position_map_center).setVisible(false);
// }
toggleMenuRotation();
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onTrackballEvent(MotionEvent event) {
// forward the event to the MapView
return map.onTrackballEvent(event);
}
// private void startMapFilePicker() {
// FilePicker.setFileDisplayFilter(FILE_FILTER_EXTENSION_MAP);
// FilePicker.setFileSelectFilter(new ValidMapFile());
// startActivityForResult(new Intent(this, FilePicker.class),
// SELECT_MAP_FILE);
// }
private void startRenderThemePicker() {
FilePicker.setFileDisplayFilter(FILE_FILTER_EXTENSION_XML);
FilePicker.setFileSelectFilter(new ValidRenderTheme());
startActivityForResult(new Intent(this, FilePicker.class),
SELECT_RENDER_THEME_FILE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
switch (requestCode) {
case POIS_REQUEST:
Log.d(TAG, "result: POIS_REQUEST");
if (resultCode == RESULT_OK) {
int id = intent.getIntExtra("ID", 0);
Log.d(TAG, "result: POIS_REQUEST: " + id);
// map.getController().setCenter(mPOIs.get(id).mLocation);
mPoiSearch.poiMarkers.showBubbleOnItem(id, map);
map.getMapViewPosition().animateTo(mPoiSearch.mPOIs.get(id).location);
}
break;
case SELECT_RENDER_THEME_FILE:
if (resultCode == RESULT_OK && intent != null
&& intent.getStringExtra(FilePicker.SELECTED_FILE) != null) {
try {
map.setRenderTheme(intent
.getStringExtra(FilePicker.SELECTED_FILE));
} catch (FileNotFoundException e) {
showToastOnUiThread(e.getLocalizedMessage());
}
}
break;
default:
break;
}
// if (requestCode == SELECT_MAP_FILE) {
// if (resultCode == RESULT_OK) {
//
// location.disableSnapToLocation(true);
//
// if (intent != null) {
// if (intent.getStringExtra(FilePicker.SELECTED_FILE) != null) {
// map.setMapFile(intent
// .getStringExtra(FilePicker.SELECTED_FILE));
// }
// }
// } else if (resultCode == RESULT_CANCELED) {
// startActivity(new Intent(this, EditPreferences.class));
// }
// } else
// if (requestCode == SELECT_RENDER_THEME_FILE && resultCode == RESULT_OK
// && intent != null
// && intent.getStringExtra(FilePicker.SELECTED_FILE) != null) {
// try {
// map.setRenderTheme(intent
// .getStringExtra(FilePicker.SELECTED_FILE));
// } catch (FileNotFoundException e) {
// showToastOnUiThread(e.getLocalizedMessage());
// }
// }
}
static boolean isPreHoneyComb() {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB;
}
@Override
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
if (id == DIALOG_ENTER_COORDINATES) {
if (mLocationDialog == null)
mLocationDialog = new LocationDialog();
return mLocationDialog.createDialog(this);
} else if (id == DIALOG_LOCATION_PROVIDER_DISABLED) {
builder.setIcon(android.R.drawable.ic_menu_info_details);
builder.setTitle(R.string.error);
builder.setMessage(R.string.no_location_provider_available);
builder.setPositiveButton(R.string.ok, null);
return builder.create();
} else {
// no dialog will be created
return null;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mLocation.disableShowMyLocation();
}
@Override
protected void onPause() {
Log.d(TAG, "onPause");
super.onPause();
// release the wake lock if necessary
if (mWakeLock.isHeld()) {
mWakeLock.release();
}
}
LocationDialog mLocationDialog;
@Override
protected void onPrepareDialog(int id, final Dialog dialog) {
if (id == DIALOG_ENTER_COORDINATES) {
mLocationDialog.prepareDialog(map, dialog);
} else {
super.onPrepareDialog(id, dialog);
}
}
@Override
protected void onResume() {
super.onResume();
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(this);
// MapScaleBar mapScaleBar = mapView.getMapScaleBar();
// mapScaleBar.setShowMapScaleBar(preferences.getBoolean("showScaleBar",
// false));
// String scaleBarUnitDefault =
// getString(R.string.preferences_scale_bar_unit_default);
// String scaleBarUnit = preferences.getString("scaleBarUnit",
// scaleBarUnitDefault);
// mapScaleBar.setImperialUnits(scaleBarUnit.equals("imperial"));
if (preferences.contains("mapDatabase")) {
String name = preferences.getString("mapDatabase",
MapDatabases.PBMAP_READER.name());
MapDatabases mapDatabaseNew;
try {
mapDatabaseNew = MapDatabases.valueOf(name);
} catch (IllegalArgumentException e) {
mapDatabaseNew = MapDatabases.PBMAP_READER;
}
if (mapDatabaseNew != mMapDatabase) {
Log.d(TAG, "set map database " + mapDatabaseNew);
map.setMapDatabase(mapDatabaseNew);
mMapDatabase = mapDatabaseNew;
}
}
// try {
// String textScaleDefault =
// getString(R.string.preferences_text_scale_default);
// map.setTextScale(Float.parseFloat(preferences.getString("textScale",
// textScaleDefault)));
// } catch (NumberFormatException e) {
// map.setTextScale(1);
// }
if (preferences.getBoolean("fullscreen", false)) {
Log.i("mapviewer", "FULLSCREEN");
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
} else {
Log.i("mapviewer", "NO FULLSCREEN");
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
}
if (preferences.getBoolean("fixOrientation", true)) {
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// this all returns the orientation which is not currently active?!
// getWindow().getWindowManager().getDefaultDisplay().getRotation());
// getWindow().getWindowManager().getDefaultDisplay().getOrientation());
}
if (preferences.getBoolean("wakeLock", false) && !mWakeLock.isHeld()) {
mWakeLock.acquire();
}
boolean drawTileFrames =
preferences.getBoolean("drawTileFrames", false);
boolean drawTileCoordinates =
preferences.getBoolean("drawTileCoordinates", false);
boolean disablePolygons =
preferences.getBoolean("disablePolygons", false);
boolean drawUnmatchedWays =
preferences.getBoolean("drawUnmatchedWays", false);
DebugSettings cur = map.getDebugSettings();
if (cur.mDisablePolygons != disablePolygons
|| cur.mDrawTileCoordinates != drawTileCoordinates
|| cur.mDrawTileFrames != drawTileFrames
|| cur.mDrawUnmatchted != drawUnmatchedWays) {
Log.d(TAG, "set map debug settings");
DebugSettings debugSettings = new DebugSettings(drawTileCoordinates,
drawTileFrames, disablePolygons, drawUnmatchedWays);
map.setDebugSettings(debugSettings);
}
// if (mMapDatabase == MapDatabases.MAP_READER) {
// if (map.getMapFile() == null)
// startMapFilePicker();
// } else {
// map.setMapFile(map.getMapFile());
// }
map.redrawMap();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(BUNDLE_SHOW_MY_LOCATION, mLocation.isShowMyLocationEnabled());
// outState.putBoolean(BUNDLE_CENTER_AT_FIRST_FIX,
// mMyLocationListener.isCenterAtFirstFix());
// outState.putBoolean(BUNDLE_SNAP_TO_LOCATION, mSnapToLocation);
}
/**
* Uses the UI thread to display the given text message as toast
* notification.
* @param text
* the text message to display
*/
void showToastOnUiThread(final String text) {
if (AndroidUtils.currentThreadIsUiThread()) {
Toast toast = Toast.makeText(this, text, Toast.LENGTH_LONG);
toast.show();
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast toast = Toast.makeText(TileMap.this, text, Toast.LENGTH_LONG);
toast.show();
}
});
}
}
//----------- Context Menu when clicking on the map
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
Log.d(TAG, "create context menu");
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.map_menu, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
Log.d(TAG, "context menu item selected " + item.getItemId());
if (mRouteSearch.onContextItemSelected(item))
return true;
return super.onContextItemSelected(item);
}
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app.filefilter;
import java.io.File;
import java.io.FileFilter;
/**
* Accepts all readable directories and all readable files with a given extension.
*/
public class FilterByFileExtension implements FileFilter {
private final String extension;
/**
* @param extension
* the allowed file name extension.
*/
public FilterByFileExtension(String extension) {
this.extension = extension;
}
@Override
public boolean accept(File file) {
// accept only readable files
if (file.canRead()) {
if (file.isDirectory()) {
// accept all directories
return true;
} else if (file.isFile() && file.getName().endsWith(this.extension)) {
return true;
}
}
return false;
}
}

View File

@@ -1,29 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app.filefilter;
import java.io.FileFilter;
import org.oscim.database.OpenResult;
/**
* An extension of the {@link FileFilter} interface.
*/
public interface ValidFileFilter extends FileFilter {
/**
* @return the result of the last {@link #accept} call (might be null).
*/
OpenResult getFileOpenResult();
}

View File

@@ -1,46 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app.filefilter;
import java.io.File;
import java.util.HashMap;
import org.oscim.database.IMapDatabase;
import org.oscim.database.OpenResult;
import org.oscim.database.mapfile.MapDatabase;
/**
* Accepts all valid map files.
*/
public final class ValidMapFile implements ValidFileFilter {
private OpenResult openResult;
@Override
public boolean accept(File file) {
IMapDatabase mapDatabase = new MapDatabase();
HashMap<String, String> options = new HashMap<String, String>();
options.put("mapfile", file.getAbsolutePath());
this.openResult = mapDatabase.open(options);
mapDatabase.close();
return this.openResult.isSuccess();
}
@Override
public OpenResult getFileOpenResult() {
return this.openResult;
}
}

View File

@@ -1,71 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app.filefilter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import org.oscim.database.OpenResult;
import org.oscim.theme.RenderThemeHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
* Accepts all valid render theme XML files.
*/
public final class ValidRenderTheme implements ValidFileFilter {
private OpenResult openResult;
@Override
public boolean accept(File file) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
RenderThemeHandler renderThemeHandler = new RenderThemeHandler();
XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
xmlReader.setContentHandler(renderThemeHandler);
xmlReader.parse(new InputSource(inputStream));
this.openResult = OpenResult.SUCCESS;
} catch (ParserConfigurationException e) {
this.openResult = new OpenResult(e.getMessage());
} catch (SAXException e) {
this.openResult = new OpenResult(e.getMessage());
} catch (IOException e) {
this.openResult = new OpenResult(e.getMessage());
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
this.openResult = new OpenResult(e.getMessage());
}
}
return this.openResult.isSuccess();
}
@Override
public OpenResult getFileOpenResult() {
return this.openResult;
}
}

View File

@@ -1,255 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app.filepicker;
import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;
import java.util.Comparator;
import org.oscim.app.R;
import org.oscim.app.filefilter.ValidFileFilter;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
/**
* A FilePicker displays the contents of directories. The user can navigate within the file system and select a single
* file whose path is then returned to the calling activity. The ordering of directory contents can be specified via
* {@link #setFileComparator(Comparator)}. By default subfolders and files are grouped and each group is ordered
* alphabetically.
* <p>
* A {@link FileFilter} can be activated via {@link #setFileDisplayFilter(FileFilter)} to restrict the displayed files
* and folders. By default all files and folders are visible.
* <p>
* Another <code>FileFilter</code> can be applied via {@link #setFileSelectFilter(ValidFileFilter)} to check if a
* selected file is valid before its path is returned. By default all files are considered as valid and can be selected.
*/
public class FilePicker extends Activity implements AdapterView.OnItemClickListener {
/**
* The name of the extra data in the result {@link Intent}.
*/
public static final String SELECTED_FILE = "selectedFile";
private static final String CURRENT_DIRECTORY = "currentDirectory";
private static final String DEFAULT_DIRECTORY = "/";
private static final int DIALOG_FILE_INVALID = 0;
// private static final int DIALOG_FILE_SELECT = 1;
private static Comparator<File> fileComparator = getDefaultFileComparator();
private static FileFilter fileDisplayFilter;
private static ValidFileFilter fileSelectFilter;
private static final String PREFERENCES_FILE = "FilePicker";
/**
* Sets the file comparator which is used to order the contents of all directories before displaying them. If set to
* null, subfolders and files will not be ordered.
*
* @param fileComparator
* the file comparator (may be null).
*/
public static void setFileComparator(Comparator<File> fileComparator) {
FilePicker.fileComparator = fileComparator;
}
/**
* Sets the file display filter. This filter is used to determine which files and subfolders of directories will be
* displayed. If set to null, all files and subfolders are shown.
*
* @param fileDisplayFilter
* the file display filter (may be null).
*/
public static void setFileDisplayFilter(FileFilter fileDisplayFilter) {
FilePicker.fileDisplayFilter = fileDisplayFilter;
}
/**
* Sets the file select filter. This filter is used when the user selects a file to determine if it is valid. If set
* to null, all files are considered as valid.
*
* @param fileSelectFilter
* the file selection filter (may be null).
*/
public static void setFileSelectFilter(ValidFileFilter fileSelectFilter) {
FilePicker.fileSelectFilter = fileSelectFilter;
}
/**
* Creates the default file comparator.
*
* @return the default file comparator.
*/
private static Comparator<File> getDefaultFileComparator() {
// order all files by type and alphabetically by name
return new Comparator<File>() {
@Override
public int compare(File file1, File file2) {
if (file1.isDirectory() && !file2.isDirectory()) {
return -1;
} else if (!file1.isDirectory() && file2.isDirectory()) {
return 1;
} else {
return file1.getName().compareToIgnoreCase(file2.getName());
}
}
};
}
private File currentDirectory;
private FilePickerIconAdapter filePickerIconAdapter;
private File[] files;
private File[] filesWithParentFolder;
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
File selectedFile = this.files[(int) id];
if (selectedFile.isDirectory()) {
this.currentDirectory = selectedFile;
browseToCurrentDirectory();
} else if (fileSelectFilter == null || fileSelectFilter.accept(selectedFile)) {
setResult(RESULT_OK,
new Intent().putExtra(SELECTED_FILE, selectedFile.getAbsolutePath()));
finish();
} else {
showDialog(DIALOG_FILE_INVALID);
}
}
/**
* Browses to the current directory.
*/
private void browseToCurrentDirectory() {
setTitle(this.currentDirectory.getAbsolutePath());
// read the subfolders and files from the current directory
if (fileDisplayFilter == null) {
this.files = this.currentDirectory.listFiles();
} else {
this.files = this.currentDirectory.listFiles(fileDisplayFilter);
}
if (this.files == null) {
this.files = new File[0];
} else {
// order the subfolders and files
Arrays.sort(this.files, fileComparator);
}
// if a parent directory exists, add it at the first position
if (this.currentDirectory.getParentFile() != null) {
this.filesWithParentFolder = new File[this.files.length + 1];
this.filesWithParentFolder[0] = this.currentDirectory.getParentFile();
System.arraycopy(this.files, 0, this.filesWithParentFolder, 1,
this.files.length);
this.files = this.filesWithParentFolder;
this.filePickerIconAdapter.setFiles(this.files, true);
} else {
this.filePickerIconAdapter.setFiles(this.files, false);
}
this.filePickerIconAdapter.notifyDataSetChanged();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_picker);
this.filePickerIconAdapter = new FilePickerIconAdapter(this);
GridView gridView = (GridView) findViewById(R.id.filePickerView);
gridView.setOnItemClickListener(this);
gridView.setAdapter(this.filePickerIconAdapter);
// if (savedInstanceState == null) {
// // first start of this instance
// showDialog(DIALOG_FILE_SELECT);
// }
}
@Override
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
switch (id) {
case DIALOG_FILE_INVALID:
builder.setIcon(android.R.drawable.ic_menu_info_details);
builder.setTitle(R.string.error);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(getString(R.string.file_invalid));
stringBuilder.append("\n\n");
stringBuilder.append(FilePicker.fileSelectFilter.getFileOpenResult()
.getErrorMessage());
builder.setMessage(stringBuilder.toString());
builder.setPositiveButton(R.string.ok, null);
return builder.create();
// case DIALOG_FILE_SELECT:
// builder.setMessage(R.string.file_select);
// builder.setPositiveButton(R.string.ok, null);
// return builder.create();
default:
// do dialog will be created
return null;
}
}
@Override
protected void onPause() {
super.onPause();
// save the current directory
Editor editor = getSharedPreferences(PREFERENCES_FILE, MODE_PRIVATE).edit();
editor.clear();
if (this.currentDirectory != null) {
editor.putString(CURRENT_DIRECTORY, this.currentDirectory.getAbsolutePath());
}
editor.commit();
}
@TargetApi(11)
@Override
protected void onResume() {
super.onResume();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
getActionBar().hide();
// check if the full screen mode should be activated
// if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen",
// false)) {
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
// getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
// } else {
// getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
// }
// restore the current directory
SharedPreferences preferences = getSharedPreferences(PREFERENCES_FILE,
MODE_PRIVATE);
this.currentDirectory = new File(preferences.getString(CURRENT_DIRECTORY,
DEFAULT_DIRECTORY));
if (!this.currentDirectory.exists() || !this.currentDirectory.canRead()) {
this.currentDirectory = new File(DEFAULT_DIRECTORY);
}
browseToCurrentDirectory();
}
}

View File

@@ -1,111 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app.filepicker;
import java.io.File;
import org.oscim.app.R;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
/**
* An adapter for the FilePicker GridView.
*/
class FilePickerIconAdapter extends BaseAdapter {
private final Context context;
private File currentFile;
private File[] files;
private boolean hasParentFolder;
private TextView textView;
/**
* Creates a new FilePickerIconAdapter with the given context.
*
* @param context
* the context of this adapter, through which new Views are created.
*/
FilePickerIconAdapter(Context context) {
super();
this.context = context;
}
@Override
public int getCount() {
if (this.files == null) {
return 0;
}
return this.files.length;
}
@Override
public Object getItem(int index) {
return this.files[index];
}
@Override
public long getItemId(int index) {
return index;
}
@Override
public View getView(int index, View convertView, ViewGroup parent) {
if (convertView instanceof TextView) {
// recycle the old view
this.textView = (TextView) convertView;
} else {
// create a new view object
this.textView = new TextView(this.context);
this.textView.setLines(2);
this.textView.setGravity(Gravity.CENTER_HORIZONTAL);
this.textView.setPadding(5, 10, 5, 10);
}
if (index == 0 && this.hasParentFolder) {
// the parent directory of the current folder
this.textView.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.file_picker_back, 0, 0);
this.textView.setText("..");
} else {
this.currentFile = this.files[index];
if (this.currentFile.isDirectory()) {
this.textView.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.file_picker_folder, 0, 0);
} else {
this.textView.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.file_picker_file, 0, 0);
}
this.textView.setText(this.currentFile.getName());
}
return this.textView;
}
/**
* Sets the data of this adapter.
*
* @param files
* the new files for this adapter.
* @param newHasParentFolder
* true if the file array has a parent folder at index 0, false otherwise.
*/
void setFiles(File[] files, boolean newHasParentFolder) {
this.files = files.clone();
this.hasParentFolder = newHasParentFolder;
}
}

View File

@@ -1,50 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app.preferences;
import org.oscim.app.R;
import android.os.Bundle;
import android.preference.PreferenceActivity;
/**
* Activity to edit the application preferences.
*/
public class EditPreferences extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
// @TargetApi(11)
@Override
protected void onResume() {
super.onResume();
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
// getActionBar().hide();
// check if the full screen mode should be activated
// if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen",
// false)) {
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
// getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
// } else {
// getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
// }
}
}

View File

@@ -1,154 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.app.preferences;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.DialogPreference;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
/**
* This abstract class provides all code for a seek bar preference. Deriving
* classes only need to set the current and
* maximum value of the seek bar. An optional text message above the seek bar is
* also supported as well as an optional
* current value message below the seek bar.
*/
abstract class SeekBarPreference extends DialogPreference implements OnSeekBarChangeListener {
private TextView mCurrentValueTextView;
private Editor mEditor;
private SeekBar mPreferenceSeekBar;
/**
* How much the value should increase when the seek bar is moved.
*/
int increment = 1;
/**
* The maximum value of the seek bar.
*/
int max;
/**
* Optional text message to display on top of the seek bar.
*/
String messageText;
/**
* The SharedPreferences instance that is used.
*/
final SharedPreferences preferencesDefault;
/**
* The current value of the seek bar.
*/
int seekBarCurrentValue;
/**
* Create a new seek bar preference.
* @param context
* the context of the seek bar preferences activity.
* @param attrs
* A set of attributes (currently ignored).
*/
SeekBarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
preferencesDefault = PreferenceManager.getDefaultSharedPreferences(context);
}
@Override
public void onClick(DialogInterface dialog, int which) {
// check if the "OK" button was pressed and the seek bar value has changed
if (which == DialogInterface.BUTTON_POSITIVE
&& seekBarCurrentValue != mPreferenceSeekBar.getProgress()) {
// get the value of the seek bar and save it in the preferences
seekBarCurrentValue = mPreferenceSeekBar.getProgress();
mEditor = preferencesDefault.edit();
mEditor.putInt(getKey(), seekBarCurrentValue);
mEditor.commit();
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mCurrentValueTextView != null) {
mCurrentValueTextView.setText(getCurrentValueText(progress));
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// do nothing
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// do nothing
}
@Override
protected View onCreateDialogView() {
// create a layout for the optional text messageText and the seek bar
LinearLayout linearLayout = new LinearLayout(getContext());
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setPadding(20, 10, 20, 10);
// check if a text message should appear above the seek bar
if (messageText != null) {
// create a text view for the text messageText
TextView messageTextView = new TextView(getContext());
messageTextView.setText(messageText);
messageTextView.setPadding(0, 0, 0, 20);
// add the text message view to the layout
linearLayout.addView(messageTextView);
}
// create the seek bar and set the maximum and current value
mPreferenceSeekBar = new SeekBar(getContext());
mPreferenceSeekBar.setOnSeekBarChangeListener(this);
mPreferenceSeekBar.setMax(max);
mPreferenceSeekBar.setProgress(Math.min(seekBarCurrentValue, max));
mPreferenceSeekBar.setKeyProgressIncrement(increment);
mPreferenceSeekBar.setPadding(0, 0, 0, 10);
// add the seek bar to the layout
linearLayout.addView(mPreferenceSeekBar);
// create the text view for the current value below the seek bar
mCurrentValueTextView = new TextView(getContext());
mCurrentValueTextView.setText(getCurrentValueText(mPreferenceSeekBar.getProgress()));
mCurrentValueTextView.setGravity(Gravity.CENTER_HORIZONTAL);
// add the current value text view to the layout
linearLayout.addView(mCurrentValueTextView);
return linearLayout;
}
/**
* Get the current value text.
* @param progress
* the current progress level of the seek bar.
* @return the new current value text
*/
abstract String getCurrentValueText(int progress);
}

View File

@@ -1,135 +0,0 @@
package org.osmdroid.location;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint;
import org.osmdroid.utils.BonusPackHelper;
import android.util.Log;
/**
* POI Provider using Flickr service to get geolocalized photos.
* @see "http://www.flickr.com/services/api/flickr.photos.search.html"
* @author M.Kergall
*/
public class FlickrPOIProvider {
protected String mApiKey;
/**
* @param apiKey
* the registered API key to give to Flickr service.
* @see "http://www.flickr.com/help/api/"
*/
public FlickrPOIProvider(String apiKey) {
mApiKey = apiKey;
}
private String getUrlInside(BoundingBox boundingBox, int maxResults) {
StringBuffer url = new StringBuffer(
"http://api.flickr.com/services/rest/?method=flickr.photos.search");
url.append("&api_key=" + mApiKey);
url.append("&bbox=" + boundingBox.getMinLongitude());
url.append("," + boundingBox.getMinLatitude());
url.append("," + boundingBox.getMaxLongitude());
url.append("," + boundingBox.getMaxLatitude());
url.append("&has_geo=1");
// url.append("&geo_context=2");
// url.append("&is_commons=true");
url.append("&format=json&nojsoncallback=1");
url.append("&per_page=" + maxResults);
// From Flickr doc:
// "Geo queries require some sort of limiting agent in order to prevent the database from crying."
// And min_date_upload is considered as a limiting agent. So:
url.append("&min_upload_date=2005/01/01");
// Ask to provide some additional attributes we will need:
url.append("&extras=geo,url_sq");
url.append("&sort=interestingness-desc");
return url.toString();
}
/* public POI getPhoto(String photoId){ String url =
* "http://api.flickr.com/services/rest/?method=flickr.photos.getInfo" +
* "&api_key=" + mApiKey + "&photo_id=" + photo Id +
* "&format=json&nojsoncallback=1"; Log.d(BonusPackHelper.LOG_TAG,
* "getPhoto:"+url); String jString =
* BonusPackHelper.requestStringFromUrl(url); if (jString == null) {
* Log.e(BonusPackHelper.LOG_TAG, "FlickrPOIProvider: request failed.");
* return null; } try { POI poi = new POI(POI.POI_SERVICE_FLICKR);
* JSONObject jRoot = new JSONObject(jString); JSONObject jPhoto =
* jRoot.getJSONObject("photo"); JSONObject jLocation =
* jPhoto.getJSONObject("location"); poi.mLocation = new GeoPoint(
* jLocation.getDouble("latitude"), jLocation.getDouble("longitude"));
* poi.mId = Long.parseLong(photoId); JSONObject jTitle =
* jPhoto.getJSONObject("title"); poi.mType = jTitle.getString("_content");
* JSONObject jDescription = jPhoto.getJSONObject("description");
* poi.mDescription = jDescription.getString("_content"); //truncate
* description if too long: if (poi.mDescription.length() > 300){
* poi.mDescription = poi.mDescription.substring(0, 300) + " (...)"; }
* String farm = jPhoto.getString("farm"); String server =
* jPhoto.getString("server"); String secret = jPhoto.getString("secret");
* JSONObject jOwner = jPhoto.getJSONObject("owner"); String nsid =
* jOwner.getString("nsid"); poi.mThumbnailPath =
* "http://farm"+farm+".staticflickr.com/"
* +server+"/"+photoId+"_"+secret+"_s.jpg"; poi.mUrl =
* "http://www.flickr.com/photos/"+nsid+"/"+photoId; return poi; }catch
* (JSONException e) { e.printStackTrace(); return null; } } */
/**
* @param fullUrl ...
* @return the list of POI
*/
public ArrayList<POI> getThem(String fullUrl) {
// for local debug: fullUrl = "http://10.0.2.2/flickr_mockup.json";
Log.d(BonusPackHelper.LOG_TAG, "FlickrPOIProvider:get:" + fullUrl);
String jString = BonusPackHelper.requestStringFromUrl(fullUrl);
if (jString == null) {
Log.e(BonusPackHelper.LOG_TAG, "FlickrPOIProvider: request failed.");
return null;
}
try {
JSONObject jRoot = new JSONObject(jString);
JSONObject jPhotos = jRoot.getJSONObject("photos");
JSONArray jPhotoArray = jPhotos.getJSONArray("photo");
int n = jPhotoArray.length();
ArrayList<POI> pois = new ArrayList<POI>(n);
for (int i = 0; i < n; i++) {
JSONObject jPhoto = jPhotoArray.getJSONObject(i);
String photoId = jPhoto.getString("id");
POI poi = new POI(POI.POI_SERVICE_FLICKR);
poi.location = new GeoPoint(
jPhoto.getDouble("latitude"),
jPhoto.getDouble("longitude"));
poi.id = Long.parseLong(photoId);
poi.type = jPhoto.getString("title");
poi.thumbnailPath = jPhoto.getString("url_sq");
String owner = jPhoto.getString("owner");
poi.url = "http://www.flickr.com/photos/" + owner + "/" + photoId;
pois.add(poi);
}
int total = jPhotos.getInt("total");
Log.d(BonusPackHelper.LOG_TAG, "done:" + n + " got, on a total of:" + total);
return pois;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
/**
* @param boundingBox ...
* @param maxResults ...
* @return list of POI, Flickr photos inside the bounding box. Null if
* technical issue.
*/
public ArrayList<POI> getPOIInside(BoundingBox boundingBox, int maxResults) {
String url = getUrlInside(boundingBox, maxResults);
return getThem(url);
}
}

View File

@@ -1,219 +0,0 @@
package org.osmdroid.location;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Locale;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint;
import org.osmdroid.utils.BonusPackHelper;
import org.osmdroid.utils.HttpConnection;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
/**
* POI Provider using GeoNames services. Currently, "find Nearby Wikipedia" and
* "Wikipedia Articles in Bounding Box" services.
* @see "http://www.geonames.org"
* @author M.Kergall
*/
public class GeoNamesPOIProvider {
protected String mUserName;
/**
* @param account
* the registered "username" to give to GeoNames service.
* @see "http://www.geonames.org/login"
*/
public GeoNamesPOIProvider(String account) {
mUserName = account;
}
private String getUrlCloseTo(GeoPoint p, int maxResults, double maxDistance) {
StringBuffer url = new StringBuffer("http://api.geonames.org/findNearbyWikipediaJSON?");
url.append("lat=" + p.getLatitude());
url.append("&lng=" + p.getLongitude());
url.append("&maxRows=" + maxResults);
url.append("&radius=" + maxDistance); //km
url.append("&lang=" + Locale.getDefault().getLanguage());
url.append("&username=" + mUserName);
return url.toString();
}
private String getUrlInside(BoundingBox boundingBox, int maxResults) {
StringBuffer url = new StringBuffer("http://api.geonames.org/wikipediaBoundingBoxJSON?");
url.append("south=" + boundingBox.getMinLatitude());
url.append("&north=" + boundingBox.getMaxLatitude());
url.append("&west=" + boundingBox.getMinLongitude());
url.append("&east=" + boundingBox.getMaxLongitude());
url.append("&maxRows=" + maxResults);
url.append("&lang=" + Locale.getDefault().getLanguage());
url.append("&username=" + mUserName);
return url.toString();
}
/**
* @param fullUrl
* ...
* @return the list of POI
*/
public ArrayList<POI> getThem(String fullUrl) {
Log.d(BonusPackHelper.LOG_TAG, "GeoNamesPOIProvider:get:" + fullUrl);
String jString = BonusPackHelper.requestStringFromUrl(fullUrl);
if (jString == null) {
Log.e(BonusPackHelper.LOG_TAG, "GeoNamesPOIProvider: request failed.");
return null;
}
try {
JSONObject jRoot = new JSONObject(jString);
JSONArray jPlaceIds = jRoot.getJSONArray("geonames");
int n = jPlaceIds.length();
ArrayList<POI> pois = new ArrayList<POI>(n);
for (int i = 0; i < n; i++) {
JSONObject jPlace = jPlaceIds.getJSONObject(i);
POI poi = new POI(POI.POI_SERVICE_GEONAMES_WIKIPEDIA);
poi.location = new GeoPoint(jPlace.getDouble("lat"),
jPlace.getDouble("lng"));
poi.category = jPlace.optString("feature");
poi.type = jPlace.getString("title");
poi.description = jPlace.optString("summary");
poi.thumbnailPath = jPlace.optString("thumbnailImg", null);
/* This makes loading too long. Thumbnail loading will be done
* only when needed, with POI.getThumbnail() if
* (poi.mThumbnailPath != null){ poi.mThumbnail =
* BonusPackHelper.loadBitmap(poi.mThumbnailPath); } */
poi.url = jPlace.optString("wikipediaUrl", null);
if (poi.url != null)
poi.url = "http://" + poi.url;
poi.rank = jPlace.optInt("rank", 0);
//other attributes: distance?
pois.add(poi);
}
Log.d(BonusPackHelper.LOG_TAG, "done");
return pois;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
//XML parsing seems 2 times slower than JSON parsing
public ArrayList<POI> getThemXML(String fullUrl) {
Log.d(BonusPackHelper.LOG_TAG, "GeoNamesPOIProvider:get:" + fullUrl);
HttpConnection connection = new HttpConnection();
connection.doGet(fullUrl);
InputStream stream = connection.getStream();
if (stream == null) {
return null;
}
GeoNamesXMLHandler handler = new GeoNamesXMLHandler();
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(stream, handler);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
connection.close();
Log.d(BonusPackHelper.LOG_TAG, "done");
return handler.mPOIs;
}
/**
* @param position
* ...
* @param maxResults
* ...
* @param maxDistance
* ... in km. 20 km max for the free service.
* @return list of POI, Wikipedia entries close to the position. Null if
* technical issue.
*/
public ArrayList<POI> getPOICloseTo(GeoPoint position,
int maxResults, double maxDistance) {
String url = getUrlCloseTo(position, maxResults, maxDistance);
return getThem(url);
}
/**
* @param boundingBox
* ...
* @param maxResults
* ...
* @return list of POI, Wikipedia entries inside the bounding box. Null if
* technical issue.
*/
public ArrayList<POI> getPOIInside(BoundingBox boundingBox, int maxResults) {
String url = getUrlInside(boundingBox, maxResults);
return getThem(url);
}
}
class GeoNamesXMLHandler extends DefaultHandler {
private String mString;
double mLat, mLng;
POI mPOI;
ArrayList<POI> mPOIs;
public GeoNamesXMLHandler() {
mPOIs = new ArrayList<POI>();
}
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) {
if (localName.equals("entry")) {
mPOI = new POI(POI.POI_SERVICE_GEONAMES_WIKIPEDIA);
}
mString = new String();
}
@Override
public void characters(char[] ch, int start, int length) {
String chars = new String(ch, start, length);
mString = mString.concat(chars);
}
@Override
public void endElement(String uri, String localName, String name) {
if (localName.equals("lat")) {
mLat = Double.parseDouble(mString);
} else if (localName.equals("lng")) {
mLng = Double.parseDouble(mString);
} else if (localName.equals("feature")) {
mPOI.category = mString;
} else if (localName.equals("title")) {
mPOI.type = mString;
} else if (localName.equals("summary")) {
mPOI.description = mString;
} else if (localName.equals("thumbnailImg")) {
if (mString != null && !mString.equals(""))
mPOI.thumbnailPath = mString;
} else if (localName.equals("wikipediaUrl")) {
if (mString != null && !mString.equals(""))
mPOI.url = "http://" + mString;
} else if (localName.equals("rank")) {
mPOI.rank = Integer.parseInt(mString);
} else if (localName.equals("entry")) {
mPOI.location = new GeoPoint(mLat, mLng);
mPOIs.add(mPOI);
}
}
}

View File

@@ -1,215 +0,0 @@
package org.osmdroid.location;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.osmdroid.utils.BonusPackHelper;
import android.content.Context;
import android.location.Address;
import android.util.Log;
/**
* Implements an equivalent to Android Geocoder class, based on OpenStreetMap
* data and Nominatim API. <br>
* See http://wiki.openstreetmap.org/wiki/Nominatim or
* http://open.mapquestapi.com/nominatim/
*
* @author M.Kergall
*/
public class GeocoderNominatim {
public static final String NOMINATIM_SERVICE_URL = "http://nominatim.openstreetmap.org/";
public static final String MAPQUEST_SERVICE_URL = "http://open.mapquestapi.com/nominatim/v1/";
protected Locale mLocale;
protected String mServiceUrl;
/**
* @param context
* ...
* @param locale
* ...
*/
protected void init(Context context, Locale locale) {
mLocale = locale;
setService(NOMINATIM_SERVICE_URL); //default service
}
public GeocoderNominatim(Context context, Locale locale) {
init(context, locale);
}
public GeocoderNominatim(Context context) {
init(context, Locale.getDefault());
}
static public boolean isPresent() {
return true;
}
/**
* Specify the url of the Nominatim service provider to use. Can be one of
* the predefined (NOMINATIM_SERVICE_URL or MAPQUEST_SERVICE_URL), or
* another one, your local instance of Nominatim for instance.
*
* @param serviceUrl
* ...
*/
public void setService(String serviceUrl) {
mServiceUrl = serviceUrl;
}
/**
* Build an Android Address object from the Nominatim address in JSON
* format. Current implementation is mainly targeting french addresses, and
* will be quite basic on other countries.
*
* @param jResult
* ...
* @return ...
* @throws JSONException
* ...
*/
protected Address buildAndroidAddress(JSONObject jResult) throws JSONException {
Address gAddress = new Address(mLocale);
gAddress.setLatitude(jResult.getDouble("lat"));
gAddress.setLongitude(jResult.getDouble("lon"));
JSONObject jAddress = jResult.getJSONObject("address");
int addressIndex = 0;
if (jAddress.has("road")) {
gAddress.setAddressLine(addressIndex++, jAddress.getString("road"));
gAddress.setThoroughfare(jAddress.getString("road"));
}
if (jAddress.has("suburb")) {
//gAddress.setAddressLine(addressIndex++, jAddress.getString("suburb"));
//not kept => often introduce "noise" in the address.
gAddress.setSubLocality(jAddress.getString("suburb"));
}
if (jAddress.has("postcode")) {
gAddress.setAddressLine(addressIndex++, jAddress.getString("postcode"));
gAddress.setPostalCode(jAddress.getString("postcode"));
}
if (jAddress.has("city")) {
gAddress.setAddressLine(addressIndex++, jAddress.getString("city"));
gAddress.setLocality(jAddress.getString("city"));
} else if (jAddress.has("town")) {
gAddress.setAddressLine(addressIndex++, jAddress.getString("town"));
gAddress.setLocality(jAddress.getString("town"));
} else if (jAddress.has("village")) {
gAddress.setAddressLine(addressIndex++, jAddress.getString("village"));
gAddress.setLocality(jAddress.getString("village"));
}
if (jAddress.has("county")) { //France: departement
gAddress.setSubAdminArea(jAddress.getString("county"));
}
if (jAddress.has("state")) { //France: region
gAddress.setAdminArea(jAddress.getString("state"));
}
if (jAddress.has("country")) {
gAddress.setAddressLine(addressIndex++, jAddress.getString("country"));
gAddress.setCountryName(jAddress.getString("country"));
}
if (jAddress.has("country_code"))
gAddress.setCountryCode(jAddress.getString("country_code"));
/*
* Other possible OSM tags in Nominatim results not handled yet: subway,
* golf_course, bus_stop, parking,... house, house_number, building
* city_district (13e Arrondissement) road => or highway, ... sub-city
* (like suburb) => locality, isolated_dwelling, hamlet ...
* state_district
*/
return gAddress;
}
/**
* @param latitude
* ...
* @param longitude
* ...
* @param maxResults
* ...
* @return ...
* @throws IOException
* ...
*/
public List<Address> getFromLocation(double latitude, double longitude, int maxResults)
throws IOException {
String url = mServiceUrl
+ "reverse?"
+ "format=json"
+ "&accept-language=" + mLocale.getLanguage()
//+ "&addressdetails=1"
+ "&lat=" + latitude
+ "&lon=" + longitude;
Log.d(BonusPackHelper.LOG_TAG, "GeocoderNominatim::getFromLocation:" + url);
String result = BonusPackHelper.requestStringFromUrl(url);
//Log.d("NOMINATIM", result);
if (result == null)
throw new IOException();
try {
JSONObject jResult = new JSONObject(result);
Address gAddress = buildAndroidAddress(jResult);
List<Address> list = new ArrayList<Address>();
list.add(gAddress);
return list;
} catch (JSONException e) {
throw new IOException();
}
}
public List<Address> getFromLocationName(String locationName, int maxResults,
double lowerLeftLatitude, double lowerLeftLongitude,
double upperRightLatitude, double upperRightLongitude)
throws IOException {
String url = mServiceUrl
+ "search?"
+ "format=json"
+ "&accept-language=" + mLocale.getLanguage()
+ "&addressdetails=1"
+ "&limit=" + maxResults
+ "&q=" + URLEncoder.encode(locationName);
if (lowerLeftLatitude != 0.0 && lowerLeftLongitude != 0.0) {
//viewbox = left, top, right, bottom:
url += "&viewbox=" + lowerLeftLongitude
+ "," + upperRightLatitude
+ "," + upperRightLongitude
+ "," + lowerLeftLatitude
+ "&bounded=1";
}
Log.d(BonusPackHelper.LOG_TAG, "GeocoderNominatim::getFromLocationName:" + url);
String result = BonusPackHelper.requestStringFromUrl(url);
//Log.d(BonusPackHelper.LOG_TAG, result);
if (result == null)
throw new IOException();
try {
JSONArray jResults = new JSONArray(result);
List<Address> list = new ArrayList<Address>();
for (int i = 0; i < jResults.length(); i++) {
JSONObject jResult = jResults.getJSONObject(i);
Address gAddress = buildAndroidAddress(jResult);
list.add(gAddress);
}
return list;
} catch (JSONException e) {
throw new IOException();
}
}
public List<Address> getFromLocationName(String locationName, int maxResults)
throws IOException {
return getFromLocationName(locationName, maxResults, 0.0, 0.0, 0.0, 0.0);
}
}

View File

@@ -1,184 +0,0 @@
package org.osmdroid.location;
import java.net.URLEncoder;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint;
import org.osmdroid.utils.BonusPackHelper;
import android.graphics.Bitmap;
import android.util.Log;
/**
* POI Provider using Nominatim service. <br>
* See https://wiki.openstreetmap.org/wiki/Nominatim<br>
* and http://open.mapquestapi.com/nominatim/<br>
*
* @author M.Kergall
*/
public class NominatimPOIProvider {
/*
* As the doc lacks a lot of features, source code may help:
* https://trac.openstreetmap
* .org/browser/applications/utils/nominatim/website/search.php featuretype=
* to select on feature type (country, city, state, settlement)<br>
* format=jsonv2 to get a place_rank<br> offset= to offset the result ?...
* <br> polygon=1 to get the border of the poi as a polygon<br> nearlat &
* nearlon = ???<br> routewidth/69 and routewidth/30 ???<br>
*/
public static final String MAPQUEST_POI_SERVICE = "http://open.mapquestapi.com/nominatim/v1/";
public static final String NOMINATIM_POI_SERVICE = "http://nominatim.openstreetmap.org/";
protected String mService;
public NominatimPOIProvider() {
mService = NOMINATIM_POI_SERVICE;
}
public void setService(String serviceUrl) {
mService = serviceUrl;
}
private StringBuffer getCommonUrl(String type, int maxResults) {
StringBuffer urlString = new StringBuffer(mService);
urlString.append("search?");
urlString.append("format=json");
urlString.append("&q=[" + URLEncoder.encode(type) + "]");
urlString.append("&limit=" + maxResults);
urlString.append("&bounded=1");
// urlString.append("&addressdetails=0");
return urlString;
}
private String getUrlInside(BoundingBox bb, String type, int maxResults) {
StringBuffer urlString = getCommonUrl(type, maxResults);
urlString.append("&viewbox=" + bb.getMaxLongitude() + ","
+ bb.getMaxLatitude() + ","
+ bb.getMinLongitude() + ","
+ bb.getMinLatitude());
return urlString.toString();
}
private String getUrlCloseTo(GeoPoint p, String type,
int maxResults, double maxDistance) {
int maxD = (int) (maxDistance * 1E6);
BoundingBox bb = new BoundingBox(p.latitudeE6 + maxD,
p.longitudeE6 + maxD,
p.latitudeE6 - maxD,
p.longitudeE6 - maxD);
return getUrlInside(bb, type, maxResults);
}
/**
* @param url
* full URL request
* @return the list of POI, of null if technical issue.
*/
public ArrayList<POI> getThem(String url) {
Log.d(BonusPackHelper.LOG_TAG, "NominatimPOIProvider:get:" + url);
String jString = BonusPackHelper.requestStringFromUrl(url);
if (jString == null) {
Log.e(BonusPackHelper.LOG_TAG, "NominatimPOIProvider: request failed.");
return null;
}
try {
JSONArray jPlaceIds = new JSONArray(jString);
int n = jPlaceIds.length();
ArrayList<POI> pois = new ArrayList<POI>(n);
Bitmap thumbnail = null;
for (int i = 0; i < n; i++) {
JSONObject jPlace = jPlaceIds.getJSONObject(i);
POI poi = new POI(POI.POI_SERVICE_NOMINATIM);
poi.id = jPlace.optLong("osm_id");
poi.location = new GeoPoint(jPlace.getDouble("lat"), jPlace.getDouble("lon"));
poi.category = jPlace.optString("class");
poi.type = jPlace.getString("type");
poi.description = jPlace.optString("display_name");
poi.thumbnailPath = jPlace.optString("icon", null);
if (i == 0 && poi.thumbnailPath != null) {
//first POI, and we have a thumbnail: load it
thumbnail = BonusPackHelper.loadBitmap(poi.thumbnailPath);
}
poi.thumbnail = thumbnail;
pois.add(poi);
}
return pois;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
/**
* @param position
* ...
* @param type
* an OpenStreetMap feature. See
* http://wiki.openstreetmap.org/wiki/Map_Features or
* http://code.google.com/p/osmbonuspack/source/browse/trunk/
* OSMBonusPackDemo/res/values/poi_tags.xml
* @param maxResults
* the maximum number of POI returned. Note that in any case,
* Nominatim will have an absolute maximum of 100.
* @param maxDistance
* to the position, in degrees. Note that it is used to build a
* bounding box around the position, not a circle.
* @return the list of POI, null if technical issue.
*/
public ArrayList<POI> getPOICloseTo(GeoPoint position, String type,
int maxResults, double maxDistance) {
String url = getUrlCloseTo(position, type, maxResults, maxDistance);
return getThem(url);
}
/**
* @param boundingBox
* ...
* @param type
* OpenStreetMap feature
* @param maxResults
* ...
* @return list of POIs, null if technical issue.
*/
public ArrayList<POI> getPOIInside(BoundingBox boundingBox, String type, int maxResults) {
String url = getUrlInside(boundingBox, type, maxResults);
return getThem(url);
}
/**
* @param path
* Warning: a long path may cause a failure due to the url to be
* too long. Using a simplified route may help (see
* Road.getRouteLow()).
* @param type
* OpenStreetMap feature
* @param maxResults
* ...
* @param maxWidth
* to the path. Certainly not in degrees. Probably in km.
* @return list of POIs, null if technical issue.
*/
public ArrayList<POI> getPOIAlong(ArrayList<GeoPoint> path, String type,
int maxResults, double maxWidth) {
StringBuffer urlString = getCommonUrl(type, maxResults);
urlString.append("&routewidth=" + maxWidth);
urlString.append("&route=");
boolean isFirst = true;
for (GeoPoint p : path) {
if (isFirst)
isFirst = false;
else
urlString.append(",");
String lat = Double.toString(p.getLatitude());
lat = lat.substring(0, Math.min(lat.length(), 7));
String lon = Double.toString(p.getLongitude());
lon = lon.substring(0, Math.min(lon.length(), 7));
urlString.append(lat + "," + lon);
//limit the size of url as much as possible, as post method is not supported.
}
return getThem(urlString.toString());
}
}

View File

@@ -1,177 +0,0 @@
package org.osmdroid.location;
import org.oscim.app.R;
import org.oscim.core.GeoPoint;
import org.osmdroid.utils.BonusPackHelper;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
/**
* Point of Interest. Exact content may depend of the POI provider used.
* @see NominatimPOIProvider
* @see GeoNamesPOIProvider
* @author M.Kergall
*/
public class POI implements Parcelable {
/** IDs of POI services */
public static int POI_SERVICE_NOMINATIM = 100;
public static int POI_SERVICE_GEONAMES_WIKIPEDIA = 200;
public static int POI_SERVICE_FLICKR = 300;
public static int POI_SERVICE_PICASA = 400;
/** Identifies the service provider of this POI. */
public int serviceId;
/** Nominatim: OSM ID. GeoNames: 0 */
public long id;
/** location of the POI */
public GeoPoint location;
/** Nominatim "class", GeoNames "feature" */
public String category;
/** type or title */
public String type;
/** can be the name, the address, a short description */
public String description;
/** url of the thumbnail. Null if none */
public String thumbnailPath;
/** the thumbnail itself. Null if none */
public Bitmap thumbnail;
/** url to a more detailed information page about this POI. Null if none */
public String url;
/**
* popularity of this POI, from 1 (lowest) to 100 (highest). 0 if not
* defined.
*/
public int rank;
/** number of attempts to load the thumbnail that have failed */
protected int mThumbnailLoadingFailures;
public POI(int serviceId) {
this.serviceId = serviceId;
// lets all other fields empty or null. That's fine.
}
protected static int MAX_LOADING_ATTEMPTS = 2;
/**
* @return the POI thumbnail as a Bitmap, if any. If not done yet, it will
* load the POI thumbnail from its url (in thumbnailPath field).
*/
public Bitmap getThumbnail() {
if (thumbnail == null && thumbnailPath != null) {
Log.d(BonusPackHelper.LOG_TAG, "POI:load thumbnail:" + thumbnailPath);
thumbnail = BonusPackHelper.loadBitmap(thumbnailPath);
if (thumbnail == null) {
mThumbnailLoadingFailures++;
if (mThumbnailLoadingFailures >= MAX_LOADING_ATTEMPTS) {
// this path really doesn't work, "kill" it for next calls:
thumbnailPath = null;
}
}
}
return thumbnail;
}
// http://stackoverflow.com/questions/7729133/using-asynctask-to-load-images-in-listview
// TODO see link, there might be a better solution
/**
* Fetch the thumbnail from its url on a thread.
* @param imageView
* to update once the thumbnail is retrieved, or to hide if no
* thumbnail.
*/
public void fetchThumbnail(final ImageView imageView) {
if (thumbnail != null) {
imageView.setImageBitmap(thumbnail);
imageView.setVisibility(View.VISIBLE);
} else if (thumbnailPath != null) {
imageView.setImageResource(R.drawable.ic_empty);
new ThumbnailTask(imageView).execute(imageView);
} else {
imageView.setVisibility(View.GONE);
}
}
class ThumbnailTask extends AsyncTask<ImageView, Void, ImageView> {
public ThumbnailTask(ImageView iv) {
iv.setTag(thumbnailPath);
}
@Override
protected ImageView doInBackground(ImageView... params) {
getThumbnail();
return params[0];
}
@Override
protected void onPostExecute(ImageView iv) {
if (thumbnailPath.equals(iv.getTag().toString()))
iv.setImageBitmap(thumbnail);
}
}
// --- Parcelable implementation
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(serviceId);
out.writeLong(id);
out.writeParcelable(location, 0);
out.writeString(category);
out.writeString(type);
out.writeString(description);
out.writeString(thumbnailPath);
out.writeParcelable(thumbnail, 0);
out.writeString(url);
out.writeInt(rank);
out.writeInt(mThumbnailLoadingFailures);
}
public static final Parcelable.Creator<POI> CREATOR = new Parcelable.Creator<POI>() {
@Override
public POI createFromParcel(Parcel in) {
POI poi = new POI(in.readInt());
poi.id = in.readLong();
poi.location = in.readParcelable(GeoPoint.class.getClassLoader());
poi.category = in.readString();
poi.type = in.readString();
poi.description = in.readString();
poi.thumbnailPath = in.readString();
poi.thumbnail = in.readParcelable(Bitmap.class.getClassLoader());
poi.url = in.readString();
poi.rank = in.readInt();
poi.mThumbnailLoadingFailures = in.readInt();
return poi;
}
@Override
public POI[] newArray(int size) {
return new POI[size];
}
};
// private POI(Parcel in) {
// serviceId = in.readInt();
// id = in.readLong();
// location = in.readParcelable(GeoPoint.class.getClassLoader());
// category = in.readString();
// type = in.readString();
// description = in.readString();
// thumbnailPath = in.readString();
// thumbnail = in.readParcelable(Bitmap.class.getClassLoader());
// url = in.readString();
// rank = in.readInt();
// mThumbnailLoadingFailures = in.readInt();
// }
}

View File

@@ -1,155 +0,0 @@
package org.osmdroid.location;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint;
import org.osmdroid.utils.BonusPackHelper;
import org.osmdroid.utils.HttpConnection;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
/** POI Provider using Picasa service.
* @see "https://developers.google.com/picasa-web/docs/2.0/reference"
* @author M.Kergall */
public class PicasaPOIProvider {
String mAccessToken;
/** @param accessToken
* the account to give to the service. Null for public access.
* @see "https://developers.google.com/picasa-web/docs/2.0/developers_guide_protocol#CreatingAccount" */
public PicasaPOIProvider(String accessToken) {
mAccessToken = accessToken;
}
private String getUrlInside(BoundingBox boundingBox, int maxResults, String query) {
StringBuffer url = new StringBuffer("http://picasaweb.google.com/data/feed/api/all?");
url.append("bbox=" + boundingBox.getMinLongitude());
url.append("," + boundingBox.getMinLatitude());
url.append("," + boundingBox.getMaxLongitude());
url.append("," + boundingBox.getMaxLatitude());
url.append("&max-results=" + maxResults);
url.append("&thumbsize=64c"); //thumbnail size: 64, cropped.
url.append("&fields=openSearch:totalResults,entry(summary,media:group/media:thumbnail,media:group/media:title,gphoto:*,georss:where,link)");
if (query != null)
url.append("&q=" + URLEncoder.encode(query));
if (mAccessToken != null) {
//TODO: warning: not tested...
url.append("&access_token=" + mAccessToken);
}
return url.toString();
}
public ArrayList<POI> getThem(String fullUrl) {
Log.d(BonusPackHelper.LOG_TAG, "PicasaPOIProvider:get:" + fullUrl);
HttpConnection connection = new HttpConnection();
connection.doGet(fullUrl);
InputStream stream = connection.getStream();
if (stream == null) {
return null;
}
PicasaXMLHandler handler = new PicasaXMLHandler();
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.getXMLReader().setFeature("http://xml.org/sax/features/namespaces", false);
parser.getXMLReader()
.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
parser.parse(stream, handler);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
connection.close();
if (handler.mPOIs != null)
Log.d(BonusPackHelper.LOG_TAG, "done:" + handler.mPOIs.size() + " got, on a total of:"
+ handler.mTotalResults);
return handler.mPOIs;
}
/** @param boundingBox
* ...
* @param maxResults
* ...
* @param query
* - optional - full-text query string. Searches the title,
* caption and tags for the specified string value.
* @return list of POI, Picasa photos inside the bounding box. Null if
* technical issue. */
public ArrayList<POI> getPOIInside(BoundingBox boundingBox, int maxResults, String query) {
String url = getUrlInside(boundingBox, maxResults, query);
return getThem(url);
}
}
class PicasaXMLHandler extends DefaultHandler {
private String mString;
double mLat, mLng;
POI mPOI;
ArrayList<POI> mPOIs;
int mTotalResults;
public PicasaXMLHandler() {
mPOIs = new ArrayList<POI>();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) {
if (qName.equals("entry")) {
mPOI = new POI(POI.POI_SERVICE_PICASA);
} else if (qName.equals("media:thumbnail")) {
mPOI.thumbnailPath = attributes.getValue("url");
} else if (qName.equals("link")) {
String rel = attributes.getValue("rel");
if ("http://schemas.google.com/photos/2007#canonical".equals(rel)) {
mPOI.url = attributes.getValue("href");
}
}
mString = new String();
}
@Override
public void characters(char[] ch, int start, int length) {
String chars = new String(ch, start, length);
mString = mString.concat(chars);
}
@Override
public void endElement(String uri, String localName, String qName) {
if (qName.equals("gml:pos")) {
String[] coords = mString.split(" ");
mLat = Double.parseDouble(coords[0]);
mLng = Double.parseDouble(coords[1]);
} else if (qName.equals("gphoto:id")) {
mPOI.id = Long.parseLong(mString);
} else if (qName.equals("media:title")) {
mPOI.type = mString;
} else if (qName.equals("summary")) {
mPOI.description = mString;
} else if (qName.equals("gphoto:albumtitle")) {
mPOI.category = mString;
} else if (qName.equals("entry")) {
mPOI.location = new GeoPoint(mLat, mLng);
mPOIs.add(mPOI);
mPOI = null;
} else if (qName.equals("openSearch:totalResults")) {
mTotalResults = Integer.parseInt(mString);
}
}
}

View File

@@ -1,100 +0,0 @@
package org.osmdroid.overlays;
import org.oscim.view.MapView;
import org.osmdroid.utils.BonusPackHelper;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
/**
* Default implementation of InfoWindow. It handles a text and a description. It
* also handles optionally a sub-description and an image. Clicking on the
* bubble will close it.
*
* @author M.Kergall
*/
public class DefaultInfoWindow extends InfoWindow {
// resource ids
private static int mTitleId = 0, mDescriptionId = 0, mSubDescriptionId = 0, mImageId = 0;
private static void setResIds(Context context) {
// get application package name
String packageName = context.getPackageName();
mTitleId = context.getResources().getIdentifier("id/bubble_title", null, packageName);
mDescriptionId = context.getResources().getIdentifier("id/bubble_description", null,
packageName);
mSubDescriptionId = context.getResources().getIdentifier("id/bubble_subdescription", null,
packageName);
mImageId = context.getResources().getIdentifier("id/bubble_image", null, packageName);
if (mTitleId == 0 || mDescriptionId == 0) {
Log.e(BonusPackHelper.LOG_TAG, "DefaultInfoWindow: unable to get res ids in "
+ packageName);
}
}
public DefaultInfoWindow(int layoutResId, MapView mapView) {
super(layoutResId, mapView);
if (mTitleId == 0)
setResIds(mapView.getContext());
// default behaviour: close it when clicking on the bubble:
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
close();
}
});
}
@Override
public void onOpen(ExtendedOverlayItem item) {
String title = item.getTitle();
if (title == null)
title = "";
((TextView) mView.findViewById(mTitleId)).setText(title);
String snippet = item.getDescription();
if (snippet == null)
snippet = "";
((TextView) mView.findViewById(mDescriptionId)).setText(snippet);
// handle sub-description, hidding or showing the text view:
TextView subDescText = (TextView) mView.findViewById(mSubDescriptionId);
String subDesc = item.getSubDescription();
if (subDesc != null && !("".equals(subDesc))) {
subDescText.setText(subDesc);
subDescText.setVisibility(View.VISIBLE);
} else {
subDescText.setVisibility(View.GONE);
}
// handle image
ImageView imageView = (ImageView) mView.findViewById(mImageId);
Drawable image = item.getImage();
if (image != null) {
// or setBackgroundDrawable(image)?
imageView.setImageDrawable(image);
imageView.setVisibility(View.VISIBLE);
} else
imageView.setVisibility(View.GONE);
}
@Override
public void onClose() {
// by default, do nothing
}
}

View File

@@ -1,168 +0,0 @@
package org.osmdroid.overlays;
import org.oscim.core.GeoPoint;
import org.oscim.overlay.OverlayItem;
import org.oscim.view.MapView;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
/**
* An OverlayItem to use in ItemizedOverlayWithBubble<br>
* - more complete: can contain an image and a sub-description that will be
* displayed in the bubble, <br>
* - and flexible: attributes are modifiable<br>
* Known Issues:<br>
* - Bubble offset is not perfect on h&xhdpi resolutions, due to an osmdroid
* issue on marker drawing<br>
* - Bubble offset is at 0 when using the default marker => set the marker on
* each item!<br>
* @see ItemizedOverlayWithBubble
* @author M.Kergall
*/
public class ExtendedOverlayItem extends OverlayItem {
// now, they are modifiable
private String mTitle, mDescription;
// now, they are modifiable
// a third field that can be displayed in
// the infowindow, on a third line
// that will be shown in the infowindow.
//unfortunately, this is not so simple...
private String mSubDescription;
private Drawable mImage;
private Object mRelatedObject; // reference to an object (of any kind)
// linked to this item.
public ExtendedOverlayItem(String aTitle, String aDescription, GeoPoint aGeoPoint) {
super(aTitle, aDescription, aGeoPoint);
mTitle = aTitle;
mDescription = aDescription;
mSubDescription = null;
mImage = null;
mRelatedObject = null;
}
public void setTitle(String aTitle) {
mTitle = aTitle;
}
public void setDescription(String aDescription) {
mDescription = aDescription;
}
public void setSubDescription(String aSubDescription) {
mSubDescription = aSubDescription;
}
public void setImage(Drawable anImage) {
mImage = anImage;
}
public void setRelatedObject(Object o) {
mRelatedObject = o;
}
@Override
public String getTitle() {
return mTitle;
}
public String getDescription() {
return mDescription;
}
public String getSubDescription() {
return mSubDescription;
}
public Drawable getImage() {
return mImage;
}
public Object getRelatedObject() {
return mRelatedObject;
}
/**
* From a HotspotPlace and drawable dimensions (width, height), return the
* hotspot position. Could be a public method of HotspotPlace or
* OverlayItem...
* @param place
* ...
* @param w
* ...
* @param h
* ...
* @return ...
*/
public Point getHotspot(HotspotPlace place, int w, int h) {
Point hp = new Point();
if (place == null)
place = HotspotPlace.BOTTOM_CENTER; // use same default than in
// osmdroid.
switch (place) {
case NONE:
hp.set(0, 0);
break;
case BOTTOM_CENTER:
hp.set(w / 2, 0);
break;
case LOWER_LEFT_CORNER:
hp.set(0, 0);
break;
case LOWER_RIGHT_CORNER:
hp.set(w, 0);
break;
case CENTER:
hp.set(w / 2, -h / 2);
break;
case LEFT_CENTER:
hp.set(0, -h / 2);
break;
case RIGHT_CENTER:
hp.set(w, -h / 2);
break;
case TOP_CENTER:
hp.set(w / 2, -h);
break;
case UPPER_LEFT_CORNER:
hp.set(0, -h);
break;
case UPPER_RIGHT_CORNER:
hp.set(w, -h);
break;
}
return hp;
}
/**
* Populates this bubble with all item info:
* <ul>
* title and description in any case,
* </ul>
* <ul>
* image and sub-description if any.
* </ul>
* and centers the map on the item. <br>
* @param bubble
* ...
* @param mapView
* ...
*/
public void showBubble(InfoWindow bubble, MapView mapView) {
// offset the bubble to be top-centered on the marker:
Drawable marker = getMarker(0 /* OverlayItem.ITEM_STATE_FOCUSED_MASK */);
int markerWidth = 0, markerHeight = 0;
if (marker != null) {
markerWidth = marker.getIntrinsicWidth();
markerHeight = marker.getIntrinsicHeight();
} // else... we don't have the default marker size => don't user default
// markers!!!
Point markerH = getHotspot(getMarkerHotspot(), markerWidth, markerHeight);
Point bubbleH = getHotspot(HotspotPlace.TOP_CENTER, markerWidth, markerHeight);
bubbleH.offset(-markerH.x, -markerH.y);
bubble.open(this, bubbleH.x, bubbleH.y);
}
}

View File

@@ -1,140 +0,0 @@
package org.osmdroid.overlays;
// TODO composite view as texture overlay and only allow one bubble at a time.
import org.oscim.view.MapView;
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
/**
* View that can be displayed on an OSMDroid map, associated to a GeoPoint.
* Typical usage: cartoon-like bubbles displayed when clicking an overlay item.
* It mimics the InfoWindow class of Google Maps JavaScript API V3. Main
* differences are:
* <ul>
* <li>Structure and content of the view is let to the responsibility of the
* caller.</li>
* <li>The same InfoWindow can be associated to many items.</li>
* </ul>
* Known issues:
* <ul>
* <li>It disappears when zooming in/out (osmdroid issue #259 on osmdroid 3.0.8,
* should be fixed in next version).</li>
* <li>The window is displayed "above" the marker, so the queue of the bubble
* can hide the marker.</li>
* </ul>
* This is an abstract class.
* @see DefaultInfoWindow
* @author M.Kergall
*/
public abstract class InfoWindow {
protected View mView;
protected boolean mIsVisible = false;
protected MapView mMapView;
protected RelativeLayout mLayout;
private android.widget.RelativeLayout.LayoutParams mLayoutPos;
/**
* @param layoutResId
* the id of the view resource.
* @param mapView
* the mapview on which is hooked the view
*/
public InfoWindow(int layoutResId, MapView mapView) {
mMapView = mapView;
mIsVisible = false;
ViewGroup parent = (ViewGroup) mapView.getParent();
Context context = mapView.getContext();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mView = inflater.inflate(layoutResId, parent, false);
RelativeLayout.LayoutParams rlp =
new RelativeLayout.LayoutParams(
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
android.view.ViewGroup.LayoutParams.MATCH_PARENT);
mLayout = new RelativeLayout(context);
mLayout.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
mLayout.setLayoutParams(rlp);
mLayoutPos = rlp;
// not so sure about this. why is just blitting the bitmap on glview so slow?...
mView.setDrawingCacheEnabled(true);
// mLayout.setDrawingCacheEnabled(true);
// mLayout.setPersistentDrawingCache(ViewGroup.PERSISTENT_ALL_CACHES);
// mLayout.setAlwaysDrawnWithCacheEnabled(true); // call this method
mLayout.setWillNotDraw(true);
mLayout.addView(mView);
}
/**
* Returns the Android view. This allows to set its content.
* @return the Android view
*/
public View getView() {
return (mView);
}
/**
* open the window at the specified position.
* @param item
* the item on which is hooked the view
* @param offsetX
* (&offsetY) the offset of the view to the position, in pixels.
* This allows to offset the view from the marker position.
* @param offsetY
* ...
*/
public void open(ExtendedOverlayItem item, int offsetX, int offsetY) {
onOpen(item);
close(); // if it was already opened
// mView.requestLayout();
mView.buildDrawingCache();
mMapView.addView(mLayout);
mIsVisible = true;
}
public void position(int x, int y) {
// if this isnt madness...
RelativeLayout.LayoutParams rlp = mLayoutPos;
rlp.leftMargin = x;
rlp.rightMargin = -x;
rlp.topMargin = -y;
rlp.bottomMargin = y + mMapView.getHeight() / 2;
mLayout.setLayoutParams(rlp);
//mMapView.requestLayout();
mLayout.requestLayout();
// using scrollTo the bubble somehow does not appear when it
// is not already in viewport...
// mLayout.scrollTo(-x, y + mMapView.getHeight() / 2);
}
public void close() {
if (mIsVisible) {
mIsVisible = false;
((ViewGroup) mLayout.getParent()).removeView(mLayout);
onClose();
}
}
public boolean isOpen() {
return mIsVisible;
}
// Abstract methods to implement:
public abstract void onOpen(ExtendedOverlayItem item);
public abstract void onClose();
}

View File

@@ -1,199 +0,0 @@
package org.osmdroid.overlays;
import java.util.List;
import org.oscim.core.GeoPoint;
import org.oscim.core.MapPosition;
import org.oscim.overlay.ItemizedIconOverlay;
import org.oscim.overlay.OverlayItem;
import org.oscim.view.MapView;
import org.osmdroid.utils.BonusPackHelper;
import android.content.Context;
import android.graphics.Point;
import android.util.Log;
/**
* An itemized overlay with an InfoWindow or "bubble" which opens when the user
* taps on an overlay item, and displays item attributes. <br>
* Items must be ExtendedOverlayItem. <br>
* @see ExtendedOverlayItem
* @see InfoWindow
* @author M.Kergall
* @param <Item>
* ...
*/
public class ItemizedOverlayWithBubble<Item extends OverlayItem> extends ItemizedIconOverlay<Item>
implements ItemizedIconOverlay.OnItemGestureListener<Item>
{
protected List<Item> mItemsList;
// only one for all items of this overlay => one at a time
protected InfoWindow mBubble;
// the item currently showing the bubble. Null if none.
protected OverlayItem mItemWithBubble;
static int layoutResId = 0;
@Override
public boolean onItemLongPress(final int index, final OverlayItem item) {
if (mBubble.isOpen())
hideBubble();
else
showBubble(index);
return false;
}
@Override
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
showBubble(index);
return false;
}
private Point mTmpPoint = new Point();
@Override
public void onUpdate(MapPosition mapPosition) {
if (mBubble.isOpen()) {
GeoPoint gp = mItemWithBubble.getPoint();
Point p = mTmpPoint;
mMapView.getMapViewPosition().project(gp, p);
mBubble.position(p.x, p.y);
}
}
public ItemizedOverlayWithBubble(final MapView mapView, final Context context,
final List<Item> aList, final InfoWindow bubble) {
super(mapView, context, aList, null);
mItemsList = aList;
if (bubble != null) {
mBubble = bubble;
} else {
// build default bubble:
String packageName = context.getPackageName();
if (layoutResId == 0) {
layoutResId = context.getResources().getIdentifier(
"layout/bonuspack_bubble", null,
packageName);
if (layoutResId == 0)
Log.e(BonusPackHelper.LOG_TAG,
"ItemizedOverlayWithBubble: layout/bonuspack_bubble not found in "
+ packageName);
}
mBubble = new DefaultInfoWindow(layoutResId, mapView);
}
mItemWithBubble = null;
mOnItemGestureListener = this;
}
public ItemizedOverlayWithBubble(final Context context, final List<Item> aList,
final MapView mapView) {
this(mapView, context, aList, null);
}
void showBubble(int index) {
showBubbleOnItem(index, mMapView);
}
/**
* Opens the bubble on the item. For each ItemizedOverlay, only one bubble
* is opened at a time. If you want more bubbles opened simultaneously, use
* many ItemizedOverlays.
* @param index
* of the overlay item to show
* @param mapView
* ...
*/
public void showBubbleOnItem(final int index, final MapView mapView) {
ExtendedOverlayItem eItem = (ExtendedOverlayItem) (getItem(index));
mItemWithBubble = eItem;
if (eItem != null) {
eItem.showBubble(mBubble, mapView);
// mMapView.getMapViewPosition().animateTo(eItem.mGeoPoint, 0);
mapView.redrawMap();
setFocus((Item) eItem);
}
}
/** Close the bubble (if it's opened). */
public void hideBubble() {
mBubble.close();
mItemWithBubble = null;
}
@Override
protected boolean onSingleTapUpHelper(final int index, final Item item, final MapView mapView) {
showBubbleOnItem(index, mapView);
return true;
}
/** @return the item currenty showing the bubble, or null if none. */
public OverlayItem getBubbledItem() {
if (mBubble.isOpen())
return mItemWithBubble;
return null;
}
/** @return the index of the item currenty showing the bubble, or -1 if none. */
public int getBubbledItemId() {
OverlayItem item = getBubbledItem();
if (item == null)
return -1;
return mItemsList.indexOf(item);
}
@Override
public boolean removeItem(final Item item) {
boolean result = super.removeItem(item);
if (mItemWithBubble == item) {
hideBubble();
}
return result;
}
@Override
public void removeAllItems() {
super.removeAllItems();
hideBubble();
}
// FIXME @Override
// public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) {
// // 1. Fixing drawing focused item on top in ItemizedOverlay (osmdroid
// // issue 354):
// if (shadow) {
// return;
// }
// final Projection pj = mapView.getProjection();
// final int size = mItemsList.size() - 1;
// final Point mCurScreenCoords = new Point();
//
// /*
// * Draw in backward cycle, so the items with the least index are on the
// * front.
// */
// for (int i = size; i >= 0; i--) {
// final Item item = getItem(i);
// if (item != mItemWithBubble) {
// pj.toMapPixels(item.mGeoPoint, mCurScreenCoords);
// onDrawItem(canvas, item, mCurScreenCoords);
// }
// }
// // draw focused item last:
// if (mItemWithBubble != null) {
// pj.toMapPixels(mItemWithBubble.mGeoPoint, mCurScreenCoords);
// onDrawItem(canvas, (Item) mItemWithBubble, mCurScreenCoords);
// }
// }
}

View File

@@ -1,58 +0,0 @@
package org.osmdroid.overlays;
import org.oscim.core.GeoPoint;
import org.oscim.overlay.Overlay;
import org.oscim.view.MapView;
import android.content.Context;
import android.view.MotionEvent;
/**
* Empty overlay than can be used to detect events on the map, and to throw them
* to a MapEventsReceiver.
*
* @see MapEventsReceiver
* @author M.Kergall
*/
public class MapEventsOverlay extends Overlay {
private MapEventsReceiver mReceiver;
/**
* @param ctx
* the context
* @param receiver
* the object that will receive/handle the events. It must
* implement MapEventsReceiver interface.
*/
public MapEventsOverlay(Context ctx, MapEventsReceiver receiver) {
super(ctx);
mReceiver = receiver;
}
// @Override
// protected void draw(Canvas c, MapView osmv, boolean shadow) {
// // Nothing to draw
// }
@Override
public boolean onSingleTapUp(MotionEvent e, MapView mapView) {
// Projection proj = mapView.getProjection();
// GeoPoint p = proj.fromPixels(e.getX(), e.getY());
GeoPoint p = mapView.getMapViewPosition().fromScreenPixels(e.getX(), e.getY());
return mReceiver.singleTapUpHelper(p);
}
@Override
public boolean onLongPress(MotionEvent e, MapView mapView) {
// Projection proj = mapView.getProjection();
// GeoPoint p = proj.fromPixels(e.getX(), e.getY());
GeoPoint p = mapView.getMapViewPosition().fromScreenPixels(e.getX(), e.getY());
// throw event to the receiver:
return mReceiver.longPressHelper(p);
}
}

View File

@@ -1,29 +0,0 @@
package org.osmdroid.overlays;
import org.oscim.core.GeoPoint;
/**
* Interface for objects that need to handle map events thrown by a
* MapEventsOverlay.
*
* @see MapEventsOverlay
* @author M.Kergall
*/
public interface MapEventsReceiver {
/**
* @param p
* the position where the event occurred.
* @return true if the event has been "consumed" and should not be handled
* by other objects.
*/
boolean singleTapUpHelper(GeoPoint p);
/**
* @param p
* the position where the event occurred.
* @return true if the event has been "consumed" and should not be handled
* by other objects.
*/
boolean longPressHelper(GeoPoint p);
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright 2012 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.osmdroid.overlays;
import java.util.List;
import org.oscim.view.MapView;
import android.content.Context;
public class POIOverlay extends ItemizedOverlayWithBubble<ExtendedOverlayItem> {
public POIOverlay(MapView mapView, Context context, List<ExtendedOverlayItem> aList,
InfoWindow bubble) {
super(mapView, context, aList, bubble);
// TODO Auto-generated constructor stub
}
}

View File

@@ -1,230 +0,0 @@
package org.osmdroid.routing;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Locale;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint;
import org.osmdroid.utils.BonusPackHelper;
import org.osmdroid.utils.HttpConnection;
import org.osmdroid.utils.PolylineEncoder;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
/**
* class to get a route between a start and a destination point, going through a
* list of waypoints. <br>
* https://developers.google.com/maps/documentation/directions/<br>
* Note that displaying a route provided by Google on a non-Google map (like
* OSM) is not allowed by Google T&C.
*
* @author M.Kergall
*/
public class GoogleRoadManager extends RoadManager {
static final String GOOGLE_DIRECTIONS_SERVICE = "http://maps.googleapis.com/maps/api/directions/xml?";
/**
* Build the URL to Google Directions service returning a route in XML
* format
*
* @param waypoints
* ...
* @return ...
*/
protected String getUrl(ArrayList<GeoPoint> waypoints) {
StringBuffer urlString = new StringBuffer(GOOGLE_DIRECTIONS_SERVICE);
urlString.append("origin=");
GeoPoint p = waypoints.get(0);
urlString.append(geoPointAsString(p));
urlString.append("&destination=");
int destinationIndex = waypoints.size() - 1;
p = waypoints.get(destinationIndex);
urlString.append(geoPointAsString(p));
for (int i = 1; i < destinationIndex; i++) {
if (i == 1)
urlString.append("&waypoints=");
else
urlString.append("%7C"); // the pipe (|), url-encoded
p = waypoints.get(i);
urlString.append(geoPointAsString(p));
}
urlString.append("&units=metric&sensor=false");
Locale locale = Locale.getDefault();
urlString.append("&language=" + locale.getLanguage());
urlString.append(mOptions);
return urlString.toString();
}
/**
* @param waypoints
* : list of GeoPoints. Must have at least 2 entries, start and
* end points.
* @return the road
*/
@Override
public Road getRoad(ArrayList<GeoPoint> waypoints) {
String url = getUrl(waypoints);
Log.d(BonusPackHelper.LOG_TAG, "GoogleRoadManager.getRoad:" + url);
Road road = null;
HttpConnection connection = new HttpConnection();
connection.doGet(url);
InputStream stream = connection.getStream();
if (stream != null)
road = getRoadXML(stream);
connection.close();
if (road == null || road.routeHigh.size() == 0) {
//Create default road:
road = new Road(waypoints);
} else {
//finalize road data update:
for (RoadLeg leg : road.legs) {
road.duration += leg.duration;
road.length += leg.length;
}
road.status = Road.STATUS_OK;
}
Log.d(BonusPackHelper.LOG_TAG, "GoogleRoadManager.getRoad - finished");
return road;
}
protected Road getRoadXML(InputStream is) {
GoogleDirectionsHandler handler = new GoogleDirectionsHandler();
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(is, handler);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return handler.mRoad;
}
}
class GoogleDirectionsHandler extends DefaultHandler {
Road mRoad;
RoadLeg mLeg;
RoadNode mNode;
boolean isPolyline, isOverviewPolyline, isLeg, isStep, isDuration, isDistance, isBB;
int mValue;
double mLat, mLng;
double mNorth, mWest, mSouth, mEast;
private String mString;
public GoogleDirectionsHandler() {
isOverviewPolyline = isBB = isPolyline = isLeg = isStep = isDuration = isDistance = false;
mRoad = new Road();
}
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) {
if (localName.equals("polyline")) {
isPolyline = true;
} else if (localName.equals("overview_polyline")) {
isOverviewPolyline = true;
} else if (localName.equals("leg")) {
mLeg = new RoadLeg();
isLeg = true;
} else if (localName.equals("step")) {
mNode = new RoadNode();
isStep = true;
} else if (localName.equals("duration")) {
isDuration = true;
} else if (localName.equals("distance")) {
isDistance = true;
} else if (localName.equals("bounds")) {
isBB = true;
}
mString = new String();
}
/**
* Overrides org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
*/
public @Override
void characters(char[] ch, int start, int length) {
String chars = new String(ch, start, length);
mString = mString.concat(chars);
}
@Override
public void endElement(String uri, String localName, String name) {
if (localName.equals("points")) {
if (isPolyline) {
//detailed piece of road for the step, to add:
ArrayList<GeoPoint> polyLine = PolylineEncoder.decode(mString, 10);
mRoad.routeHigh.addAll(polyLine);
} else if (isOverviewPolyline) {
//low-def polyline for the whole road:
mRoad.setRouteLow(PolylineEncoder.decode(mString, 10));
}
} else if (localName.equals("polyline")) {
isPolyline = false;
} else if (localName.equals("overview_polyline")) {
isOverviewPolyline = false;
} else if (localName.equals("value")) {
mValue = Integer.parseInt(mString);
} else if (localName.equals("duration")) {
if (isStep)
mNode.duration = mValue;
else
mLeg.duration = mValue;
isDuration = false;
} else if (localName.equals("distance")) {
if (isStep)
mNode.length = mValue / 1000.0;
else
mLeg.length = mValue / 1000.0;
isDistance = false;
} else if (localName.equals("html_instructions")) {
if (isStep) {
mString = mString.replaceAll("<[^>]*>", " "); //remove everything in <...>
mString = mString.replaceAll("&nbsp;", " ");
mNode.instructions = mString;
//Log.d(BonusPackHelper.LOG_TAG, mString);
}
} else if (localName.equals("start_location")) {
if (isStep)
mNode.location = new GeoPoint(mLat, mLng);
} else if (localName.equals("step")) {
mRoad.nodes.add(mNode);
isStep = false;
} else if (localName.equals("leg")) {
mRoad.legs.add(mLeg);
isLeg = false;
} else if (localName.equals("lat")) {
mLat = Double.parseDouble(mString);
} else if (localName.equals("lng")) {
mLng = Double.parseDouble(mString);
} else if (localName.equals("northeast")) {
if (isBB) {
mNorth = mLat;
mEast = mLng;
}
} else if (localName.equals("southwest")) {
if (isBB) {
mSouth = mLat;
mWest = mLng;
}
} else if (localName.equals("bounds")) {
mRoad.boundingBox = new BoundingBox(mNorth, mEast, mSouth, mWest);
isBB = false;
}
}
}

View File

@@ -1,278 +0,0 @@
package org.osmdroid.routing;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint;
import org.osmdroid.utils.BonusPackHelper;
import org.osmdroid.utils.HttpConnection;
import org.osmdroid.utils.PolylineEncoder;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
/**
* class to get a route between a start and a destination point, going through a
* list of waypoints. It uses MapQuest open, public and free API, based on
* OpenStreetMap data. <br>
* See http://open.mapquestapi.com/guidance
*
* @author M.Kergall
*/
public class MapQuestRoadManager extends RoadManager {
static final String MAPQUEST_GUIDANCE_SERVICE = "http://open.mapquestapi.com/guidance/v0/route?";
/**
* Build the URL to MapQuest service returning a route in XML format
*
* @param waypoints
* : array of waypoints, as [lat, lng], from start point to end
* point.
* @return ...
*/
protected String getUrl(ArrayList<GeoPoint> waypoints) {
StringBuffer urlString = new StringBuffer(MAPQUEST_GUIDANCE_SERVICE);
urlString.append("from=");
GeoPoint p = waypoints.get(0);
urlString.append(geoPointAsString(p));
for (int i = 1; i < waypoints.size(); i++) {
p = waypoints.get(i);
urlString.append("&to=" + geoPointAsString(p));
}
urlString.append("&outFormat=xml");
urlString.append("&shapeFormat=cmp"); // encoded polyline, much faster
urlString.append("&narrativeType=text"); // or "none"
// Locale locale = Locale.getDefault();
// urlString.append("&locale="+locale.getLanguage()+"_"+locale.getCountry());
urlString.append("&unit=k&fishbone=false");
// urlString.append("&generalizeAfter=500" /*+&generalize=2"*/);
// 500 points max, 2 meters tolerance
// Warning: MapQuest Open API doc is sometimes WRONG:
// - use unit, not units
// - use fishbone, not enableFishbone
// - locale (fr_FR, en_US) is supported but not documented.
// - generalize and generalizeAfter are not properly implemented
urlString.append(mOptions);
return urlString.toString();
}
/**
* @param waypoints
* : list of GeoPoints. Must have at least 2 entries, start and
* end points.
* @return the road
*/
@Override
public Road getRoad(ArrayList<GeoPoint> waypoints) {
String url = getUrl(waypoints);
Log.d(BonusPackHelper.LOG_TAG, "MapQuestRoadManager.getRoute:" + url);
Road road = null;
HttpConnection connection = new HttpConnection();
connection.doGet(url);
InputStream stream = connection.getStream();
if (stream != null)
road = getRoadXML(stream, waypoints);
if (road == null || road.routeHigh.size() == 0) {
// Create default road:
road = new Road(waypoints);
}
connection.close();
Log.d(BonusPackHelper.LOG_TAG, "MapQuestRoadManager.getRoute - finished");
return road;
}
/**
* XML implementation
*
* @param is
* : input stream to parse
* @param waypoints
* ...
* @return the road ...
*/
protected Road getRoadXML(InputStream is, ArrayList<GeoPoint> waypoints) {
XMLHandler handler = new XMLHandler();
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(is, handler);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Road road = handler.mRoad;
if (road != null && road.routeHigh.size() > 0) {
road.nodes = finalizeNodes(road.nodes, handler.mLinks, road.routeHigh);
road.buildLegs(waypoints);
road.status = Road.STATUS_OK;
}
return road;
}
protected ArrayList<RoadNode> finalizeNodes(ArrayList<RoadNode> mNodes,
ArrayList<RoadLink> mLinks, ArrayList<GeoPoint> polyline) {
int n = mNodes.size();
if (n == 0)
return mNodes;
ArrayList<RoadNode> newNodes = new ArrayList<RoadNode>(n);
RoadNode lastNode = null;
for (int i = 1; i < n - 1; i++) { // 1, n-1 => first and last MapQuest
// nodes are irrelevant.
RoadNode node = mNodes.get(i);
RoadLink link = mLinks.get(node.nextRoadLink);
if (lastNode != null && (node.instructions == null || node.maneuverType == 0)) {
// this node is irrelevant, don't keep it,
// but update values of last node:
lastNode.length += link.mLength;
lastNode.duration += (node.duration + link.mDuration);
} else {
node.length = link.mLength;
node.duration += link.mDuration;
int locationIndex = link.mShapeIndex;
node.location = polyline.get(locationIndex);
newNodes.add(node);
lastNode = node;
}
}
// switch to the new array of nodes:
return newNodes;
}
}
/** Road Link is a portion of road between 2 "nodes" or intersections */
class RoadLink {
/** in km/h */
public double mSpeed;
/** in km */
public double mLength;
/** in sec */
public double mDuration;
/** starting point of the link, as index in initial polyline */
public int mShapeIndex;
}
/**
* XMLHandler: class to handle XML generated by MapQuest "guidance" open API.
*/
class XMLHandler extends DefaultHandler {
public Road mRoad;
public ArrayList<RoadLink> mLinks;
boolean isBB;
boolean isGuidanceNodeCollection;
private String mString;
double mLat, mLng;
double mNorth, mWest, mSouth, mEast;
RoadLink mLink;
RoadNode mNode;
public XMLHandler() {
isBB = isGuidanceNodeCollection = false;
mRoad = new Road();
mLinks = new ArrayList<RoadLink>();
}
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) {
if (localName.equals("boundingBox"))
isBB = true;
else if (localName.equals("link"))
mLink = new RoadLink();
else if (localName.equals("node"))
mNode = new RoadNode();
else if (localName.equals("GuidanceNodeCollection"))
isGuidanceNodeCollection = true;
mString = new String();
}
/**
* Overrides org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
*/
@Override
public void characters(char[] ch, int start, int length) {
String chars = new String(ch, start, length);
mString = mString.concat(chars);
}
@Override
public void endElement(String uri, String localName, String name) {
if (localName.equals("lat")) {
mLat = Double.parseDouble(mString);
} else if (localName.equals("lng")) {
mLng = Double.parseDouble(mString);
} else if (localName.equals("shapePoints")) {
mRoad.routeHigh = PolylineEncoder.decode(mString, 10);
// Log.d("DD", "High="+mRoad.mRouteHigh.size());
} else if (localName.equals("generalizedShape")) {
mRoad.setRouteLow(PolylineEncoder.decode(mString, 10));
// Log.d("DD", "Low="+mRoad.mRouteLow.size());
} else if (localName.equals("length")) {
mLink.mLength = Double.parseDouble(mString);
} else if (localName.equals("speed")) {
mLink.mSpeed = Double.parseDouble(mString);
} else if (localName.equals("shapeIndex")) {
mLink.mShapeIndex = Integer.parseInt(mString);
} else if (localName.equals("link")) {
// End of a link: update road attributes:
// GuidanceLinkCollection could in theory contain additional unused
// links,
// but normally not with fishbone set to false.
mLink.mDuration = mLink.mLength / mLink.mSpeed * 3600.0;
mLinks.add(mLink);
mRoad.length += mLink.mLength;
mRoad.duration += mLink.mDuration;
mLink = null;
} else if (localName.equals("turnCost")) {
int turnCost = Integer.parseInt(mString);
mNode.duration += turnCost;
mRoad.duration += turnCost;
} else if (localName.equals("maneuverType")) {
mNode.maneuverType = Integer.parseInt(mString);
} else if (localName.equals("info")) {
if (isGuidanceNodeCollection) {
if (mNode.instructions == null)
// this is first "info" value for this node, keep it:
mNode.instructions = mString;
}
} else if (localName.equals("linkId")) {
if (isGuidanceNodeCollection)
mNode.nextRoadLink = Integer.parseInt(mString);
} else if (localName.equals("node")) {
mRoad.nodes.add(mNode);
mNode = null;
} else if (localName.equals("GuidanceNodeCollection")) {
isGuidanceNodeCollection = false;
} else if (localName.equals("ul")) {
if (isBB) {
mNorth = mLat;
mWest = mLng;
}
} else if (localName.equals("lr")) {
if (isBB) {
mSouth = mLat;
mEast = mLng;
}
} else if (localName.equals("boundingBox")) {
mRoad.boundingBox = new BoundingBox(mNorth, mEast, mSouth, mWest);
isBB = false;
}
}
}

View File

@@ -1,278 +0,0 @@
package org.osmdroid.routing;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint;
import org.osmdroid.utils.BonusPackHelper;
import org.osmdroid.utils.HttpConnection;
import org.osmdroid.utils.PolylineEncoder;
import android.util.Log;
/**
* get a route between a start and a destination point. It uses OSRM, a free
* open source routing service based on OpenSteetMap data. <br>
* See https://github.com/DennisOSRM/Project-OSRM/wiki/Server-api<br>
* It requests by default the OSRM demo site. Use setService() to request an
* other (for instance your own) OSRM service. <br>
* TODO: improve internationalization of instructions
* @author M.Kergall
*/
public class OSRMRoadManager extends RoadManager {
static final String OSRM_SERVICE = "http://router.project-osrm.org/viaroute?";
//Note that the result of OSRM is quite close to Cloudmade NavEngine format:
//http://developers.cloudmade.com/wiki/navengine/JSON_format
protected String mServiceUrl;
protected String mUserAgent;
/** mapping from OSRM directions to MapQuest maneuver IDs: */
static final HashMap<String, Integer> MANEUVERS;
static {
MANEUVERS = new HashMap<String, Integer>();
MANEUVERS.put("0", Integer.valueOf(0)); //No instruction
MANEUVERS.put("1", Integer.valueOf(1)); //Continue
MANEUVERS.put("2", Integer.valueOf(6)); //Slight right
MANEUVERS.put("3", Integer.valueOf(7)); //Right
MANEUVERS.put("4", Integer.valueOf(8)); //Sharp right
MANEUVERS.put("5", Integer.valueOf(12)); //U-turn
MANEUVERS.put("6", Integer.valueOf(5)); //Sharp left
MANEUVERS.put("7", Integer.valueOf(4)); //Left
MANEUVERS.put("8", Integer.valueOf(3)); //Slight left
MANEUVERS.put("9", Integer.valueOf(24)); //Arrived (at waypoint)
//MANEUVERS.put("10", Integer.valueOf(0)); //"Head" => used by OSRM as the start node
MANEUVERS.put("11-1", Integer.valueOf(27)); //Round-about, 1st exit
MANEUVERS.put("11-2", Integer.valueOf(28)); //2nd exit, etc ...
MANEUVERS.put("11-3", Integer.valueOf(29));
MANEUVERS.put("11-4", Integer.valueOf(30));
MANEUVERS.put("11-5", Integer.valueOf(31));
MANEUVERS.put("11-6", Integer.valueOf(32));
MANEUVERS.put("11-7", Integer.valueOf(33));
MANEUVERS.put("11-8", Integer.valueOf(34)); //Round-about, 8th exit
MANEUVERS.put("15", Integer.valueOf(24)); //Arrived
}
//From: Project-OSRM-Web / WebContent / localization / OSRM.Locale.en.js
// driving directions
// %s: road name
// %d: direction => removed
// <*>: will only be printed when there actually is a road name
static final HashMap<String, HashMap<String, String>> DIRECTIONS;
static {
DIRECTIONS = new HashMap<String, HashMap<String, String>>();
HashMap<String, String> directions;
directions = new HashMap<String, String>();
DIRECTIONS.put("en", directions);
directions.put("0", "Unknown instruction< on %s>");
directions.put("1", "Continue< on %s>");
directions.put("2", "Turn slight right< on %s>");
directions.put("3", "Turn right< on %s>");
directions.put("4", "Turn sharp right< on %s>");
directions.put("5", "U-Turn< on %s>");
directions.put("6", "Turn sharp left< on %s>");
directions.put("7", "Turn left< on %s>");
directions.put("8", "Turn slight left< on %s>");
directions.put("9", "You have reached a waypoint of your trip");
directions.put("10", "<Go on %s>");
directions.put("11-1", "Enter roundabout and leave at first exit< on %s>");
directions.put("11-2", "Enter roundabout and leave at second exit< on %s>");
directions.put("11-3", "Enter roundabout and leave at third exit< on %s>");
directions.put("11-4", "Enter roundabout and leave at fourth exit< on %s>");
directions.put("11-5", "Enter roundabout and leave at fifth exit< on %s>");
directions.put("11-6", "Enter roundabout and leave at sixth exit< on %s>");
directions.put("11-7", "Enter roundabout and leave at seventh exit< on %s>");
directions.put("11-8", "Enter roundabout and leave at eighth exit< on %s>");
directions.put("11-9", "Enter roundabout and leave at nineth exit< on %s>");
directions.put("15", "You have reached your destination");
directions = new HashMap<String, String>();
DIRECTIONS.put("fr", directions);
directions.put("0", "Instruction inconnue< sur %s>");
directions.put("1", "Continuez< sur %s>");
directions.put("2", "Tournez légèrement à droite< sur %s>");
directions.put("3", "Tournez à droite< sur %s>");
directions.put("4", "Tournez fortement à droite< sur %s>");
directions.put("5", "Faites demi-tour< sur %s>");
directions.put("6", "Tournez fortement à gauche< sur %s>");
directions.put("7", "Tournez à gauche< sur %s>");
directions.put("8", "Tournez légèrement à gauche< sur %s>");
directions.put("9", "Vous êtes arrivé à une étape de votre voyage");
directions.put("10", "<Prenez %s>");
directions.put("11-1", "Au rond-point, prenez la première sortie< sur %s>");
directions.put("11-2", "Au rond-point, prenez la deuxième sortie< sur %s>");
directions.put("11-3", "Au rond-point, prenez la troisième sortie< sur %s>");
directions.put("11-4", "Au rond-point, prenez la quatrième sortie< sur %s>");
directions.put("11-5", "Au rond-point, prenez la cinquième sortie< sur %s>");
directions.put("11-6", "Au rond-point, prenez la sixième sortie< sur %s>");
directions.put("11-7", "Au rond-point, prenez la septième sortie< sur %s>");
directions.put("11-8", "Au rond-point, prenez la huitième sortie< sur %s>");
directions.put("11-9", "Au rond-point, prenez la neuvième sortie< sur %s>");
directions.put("15", "Vous êtes arrivé");
directions = new HashMap<String, String>();
DIRECTIONS.put("pl", directions);
directions.put("0", "Nieznana instrukcja<w %s>");
directions.put("1", "Kontynuuj jazdę<na %s>");
directions.put("2", "Skręć lekko w prawo<w %s>");
directions.put("3", "Skręć w prawo<w %s>");
directions.put("4", "Skręć ostro w prawo<w %s>");
directions.put("5", "Zawróć<na %s>");
directions.put("6", "Skręć ostro w lewo<w %s>");
directions.put("7", "Skręć w lewo<w %s>");
directions.put("8", "Skręć lekko w lewo<w %s>");
directions.put("9", "Dotarłeś do punktu pośredniego");
directions.put("10", "<Jedź %s>");
directions.put("11-1", "Wjedź na rondo i opuść je pierwszym zjazdem<w %s>");
directions.put("11-2", "Wjedź na rondo i opuść je drugim zjazdem<w %s>");
directions.put("11-3", "Wjedź na rondo i opuść je trzecim zjazdem<w %s>");
directions.put("11-4", "Wjedź na rondo i opuść je czwartym zjazdem<w %s>");
directions.put("11-5", "Wjedź na rondo i opuść je piątym zjazdem<w %s>");
directions.put("11-6", "Wjedź na rondo i opuść je szóstym zjazdem<w %s>");
directions.put("11-7", "Wjedź na rondo i opuść je siódmym zjazdem<w %s>");
directions.put("11-8", "Wjedź na rondo i opuść je ósmym zjazdem<w %s>");
directions.put("11-9", "Wjedź na rondo i opuść je dziewiątym zjazdem<w %s>");
directions.put("15", "Dotarłeś do celu podróży");
}
public OSRMRoadManager() {
super();
mServiceUrl = OSRM_SERVICE;
mUserAgent = BonusPackHelper.DEFAULT_USER_AGENT; //set user agent to the default one.
}
/**
* allows to request on an other site than OSRM demo site
* @param serviceUrl
* ...
*/
public void setService(String serviceUrl) {
mServiceUrl = serviceUrl;
}
/**
* allows to send to OSRM service a user agent specific to the app, instead
* of the default user agent of OSMBonusPack lib.
* @param userAgent
* ...
*/
public void setUserAgent(String userAgent) {
mUserAgent = userAgent;
}
protected String getUrl(ArrayList<GeoPoint> waypoints) {
StringBuffer urlString = new StringBuffer(mServiceUrl);
for (int i = 0; i < waypoints.size(); i++) {
GeoPoint p = waypoints.get(i);
urlString.append("&loc=" + geoPointAsString(p));
}
urlString.append(mOptions);
return urlString.toString();
}
@Override
public Road getRoad(ArrayList<GeoPoint> waypoints) {
String url = getUrl(waypoints);
Log.d(BonusPackHelper.LOG_TAG, "OSRMRoadManager.getRoad:" + url);
//String jString = BonusPackHelper.requestStringFromUrl(url);
HttpConnection connection = new HttpConnection();
connection.setUserAgent(mUserAgent);
connection.doGet(url);
String jString = connection.getContentAsString();
connection.close();
if (jString == null) {
Log.e(BonusPackHelper.LOG_TAG, "OSRMRoadManager::getRoad: request failed.");
return new Road(waypoints);
}
Locale l = Locale.getDefault();
HashMap<String, String> directions = DIRECTIONS.get(l.getLanguage());
if (directions == null)
directions = DIRECTIONS.get("en");
Road road = new Road();
try {
JSONObject jObject = new JSONObject(jString);
String route_geometry = jObject.getString("route_geometry");
road.routeHigh = PolylineEncoder.decode(route_geometry, 10);
JSONArray jInstructions = jObject.getJSONArray("route_instructions");
int n = jInstructions.length();
RoadNode lastNode = null;
for (int i = 0; i < n; i++) {
JSONArray jInstruction = jInstructions.getJSONArray(i);
RoadNode node = new RoadNode();
int positionIndex = jInstruction.getInt(3);
node.location = road.routeHigh.get(positionIndex);
node.length = jInstruction.getInt(2) / 1000.0;
node.duration = jInstruction.getInt(4); //Segment duration in seconds.
String direction = jInstruction.getString(0);
String roadName = jInstruction.getString(1);
if (lastNode != null && "1".equals(direction) && "".equals(roadName)) {
//node "Continue" with no road name is useless, don't add it
lastNode.length += node.length;
lastNode.duration += node.duration;
} else {
node.maneuverType = getManeuverCode(direction);
node.instructions = buildInstructions(direction, roadName, directions);
//Log.d(BonusPackHelper.LOG_TAG, direction+"=>"+node.mManeuverType+"; "+node.mInstructions);
road.nodes.add(node);
lastNode = node;
}
}
JSONObject jSummary = jObject.getJSONObject("route_summary");
road.length = jSummary.getInt("total_distance") / 1000.0;
road.duration = jSummary.getInt("total_time");
} catch (JSONException e) {
e.printStackTrace();
return new Road(waypoints);
}
if (road.routeHigh.size() == 0) {
//Create default road:
road = new Road(waypoints);
} else {
road.buildLegs(waypoints);
BoundingBox bb = BoundingBox.fromGeoPoints(road.routeHigh);
//Correcting osmdroid bug #359:
road.boundingBox = bb;
// new BoundingBox(
// bb.getLatSouthE6(), bb.getLonWestE6(), bb.getLatNorthE6(), bb.getLonEastE6());
road.status = Road.STATUS_OK;
}
Log.d(BonusPackHelper.LOG_TAG, "OSRMRoadManager.getRoad - finished");
return road;
}
protected int getManeuverCode(String direction) {
Integer code = MANEUVERS.get(direction);
if (code != null)
return code.intValue();
return 0;
}
protected String buildInstructions(String direction, String roadName,
HashMap<String, String> directions) {
if (directions == null)
return null;
direction = directions.get(direction);
if (direction == null)
return null;
String instructions = null;
if (roadName.equals(""))
//remove "<*>"
instructions = direction.replaceFirst("<[^>]*>", "");
else {
direction = direction.replace('<', ' ');
direction = direction.replace('>', ' ');
instructions = String.format(direction, roadName);
}
return instructions;
}
}

View File

@@ -1,240 +0,0 @@
package org.osmdroid.routing;
import java.util.ArrayList;
import org.oscim.core.BoundingBox;
import org.oscim.core.GeoPoint;
import org.osmdroid.utils.BonusPackHelper;
import org.osmdroid.utils.DouglasPeuckerReducer;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
/**
* describes the way to go from a position to an other. Normally returned by a
* call to a Directions API (from MapQuest, GoogleMaps or other)
* @see MapQuestRoadManager
* @see GoogleRoadManager
* @see OSRMRoadManager
* @author M.Kergall
*/
public class Road implements Parcelable {
/**
* @see #STATUS_INVALID STATUS_INVALID
* @see #STATUS_OK STATUS_OK
* @see #STATUS_DEFAULT STATUS_DEFAULT
*/
public int status;
/** length of the whole route in km. */
public double length;
/** duration of the whole trip in sec. */
public double duration;
public ArrayList<RoadNode> nodes;
/** */
/** there is one leg between each waypoint */
public ArrayList<RoadLeg> legs;
/** full shape: polyline, as an array of GeoPoints */
public ArrayList<GeoPoint> routeHigh;
/** the same, in low resolution (less points) */
private ArrayList<GeoPoint> routeLow;
/** road bounding box */
public BoundingBox boundingBox;
/** STATUS_INVALID = road not built */
public static final int STATUS_INVALID = 0;
/** STATUS_OK = road properly retrieved and built */
public static final int STATUS_OK = 1;
/**
* STATUS_DEFAULT = any issue (technical issue, or no possible route) led to
* build a default road
*/
public static final int STATUS_DEFAULT = 2;
private void init() {
status = STATUS_INVALID;
length = 0.0;
duration = 0.0;
nodes = new ArrayList<RoadNode>();
routeHigh = new ArrayList<GeoPoint>();
routeLow = null;
legs = new ArrayList<RoadLeg>();
boundingBox = null;
}
public Road() {
init();
}
/**
* default constructor when normal loading failed: the road shape only
* contains the waypoints; All distances and times are at 0; there is no
* node; status equals DEFAULT.
* @param waypoints
* ...
*/
public Road(ArrayList<GeoPoint> waypoints) {
init();
int n = waypoints.size();
for (int i = 0; i < n; i++) {
GeoPoint p = waypoints.get(i);
routeHigh.add(p);
}
for (int i = 0; i < n - 1; i++) {
RoadLeg leg = new RoadLeg(/* i, i+1, mLinks */);
legs.add(leg);
}
boundingBox = BoundingBox.fromGeoPoints(routeHigh);
status = STATUS_DEFAULT;
}
/**
* @return the road shape in "low resolution" = simplified by around 10
* factor.
*/
public ArrayList<GeoPoint> getRouteLow() {
if (routeLow == null) {
// Simplify the route (divide number of points by around 10):
int n = routeHigh.size();
routeLow = DouglasPeuckerReducer.reduceWithTolerance(routeHigh, 1500.0);
Log.d(BonusPackHelper.LOG_TAG, "Road reduced from " + n + " to " + routeLow.size()
+ " points");
}
return routeLow;
}
public void setRouteLow(ArrayList<GeoPoint> route) {
routeLow = route;
}
/**
* @param pLength
* in km
* @param pDuration
* in sec
* @return a human-readable length&duration text.
*/
public String getLengthDurationText(double pLength, double pDuration) {
String result;
if (pLength >= 100.0) {
result = (int) (pLength) + " km, ";
} else if (pLength >= 1.0) {
result = Math.round(pLength * 10) / 10.0 + " km, ";
} else {
result = (int) (pLength * 1000) + " m, ";
}
int totalSeconds = (int) pDuration;
int hours = totalSeconds / 3600;
int minutes = (totalSeconds / 60) - (hours * 60);
int seconds = (totalSeconds % 60);
if (hours != 0) {
result += hours + " h ";
}
if (minutes != 0) {
result += minutes + " min";
}
if (hours == 0 && minutes == 0) {
result += seconds + " s";
}
return result;
}
/**
* @return length and duration of the whole road, or of a leg of the road,
* as a String, in a readable format.
* @param leg
* leg index, starting from 0. -1 for the whole road
*/
public String getLengthDurationText(int leg) {
double len = (leg == -1 ? this.length : legs.get(leg).length);
double dur = (leg == -1 ? this.duration : legs.get(leg).duration);
return getLengthDurationText(len, dur);
}
protected double distanceLLSquared(GeoPoint p1, GeoPoint p2) {
double deltaLat = p2.latitudeE6 - p1.latitudeE6;
double deltaLon = p2.longitudeE6 - p1.longitudeE6;
return (deltaLat * deltaLat + deltaLon * deltaLon);
}
/**
* As MapQuest and OSRM doesn't provide legs information, we have to rebuild
* it, using the waypoints and the road nodes. <br>
* Note that MapQuest legs fit well with waypoints, as there is a
* "dedicated" node for each waypoint. But OSRM legs are not precise, as
* there is no node "dedicated" to waypoints.
* @param waypoints
* ...
*/
public void buildLegs(ArrayList<GeoPoint> waypoints) {
legs = new ArrayList<RoadLeg>();
int firstNodeIndex = 0;
// For all intermediate waypoints, search the node closest to the
// waypoint
int w = waypoints.size();
int n = nodes.size();
for (int i = 1; i < w - 1; i++) {
GeoPoint waypoint = waypoints.get(i);
double distanceMin = -1.0;
int nodeIndexMin = -1;
for (int j = firstNodeIndex; j < n; j++) {
GeoPoint roadPoint = nodes.get(j).location;
double dSquared = distanceLLSquared(roadPoint, waypoint);
if (nodeIndexMin == -1 || dSquared < distanceMin) {
distanceMin = dSquared;
nodeIndexMin = j;
}
}
// Build the leg as ending with this closest node:
RoadLeg leg = new RoadLeg(firstNodeIndex, nodeIndexMin, nodes);
legs.add(leg);
firstNodeIndex = nodeIndexMin + 1; // restart next leg from end
}
// Build last leg ending with last node:
RoadLeg lastLeg = new RoadLeg(firstNodeIndex, n - 1, nodes);
legs.add(lastLeg);
}
// --- Parcelable implementation
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(status);
out.writeDouble(length);
out.writeDouble(duration);
out.writeList(nodes);
out.writeList(legs);
out.writeList(routeHigh);
out.writeParcelable(boundingBox, 0);
}
public static final Parcelable.Creator<Road> CREATOR = new Parcelable.Creator<Road>() {
@Override
public Road createFromParcel(Parcel source) {
return new Road(source);
}
@Override
public Road[] newArray(int size) {
return new Road[size];
}
};
@SuppressWarnings("unchecked")
private Road(Parcel in) {
status = in.readInt();
length = in.readDouble();
duration = in.readDouble();
nodes = in.readArrayList(RoadNode.class.getClassLoader());
legs = in.readArrayList(RoadLeg.class.getClassLoader());
routeHigh = in.readArrayList(GeoPoint.class.getClassLoader());
boundingBox = in.readParcelable(BoundingBox.class.getClassLoader());
}
}

View File

@@ -1,78 +0,0 @@
package org.osmdroid.routing;
import java.util.ArrayList;
import org.osmdroid.utils.BonusPackHelper;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
/**
* Road Leg is the portion of the road between 2 waypoints (intermediate points
* requested)
*
* @author M.Kergall
*/
public class RoadLeg implements Parcelable {
/** in km */
public double length;
/** in sec */
public double duration;
/** starting node of the leg, as index in nodes array */
public int startNodeIndex;
/** and ending node */
public int endNodeIndex;
public RoadLeg() {
length = duration = 0.0;
startNodeIndex = endNodeIndex = 0;
}
public RoadLeg(int startNodeIndex, int endNodeIndex,
ArrayList<RoadNode> nodes) {
this.startNodeIndex = startNodeIndex;
this.endNodeIndex = endNodeIndex;
length = duration = 0.0;
for (int i = startNodeIndex; i <= endNodeIndex; i++) {
RoadNode node = nodes.get(i);
length += node.length;
duration += node.duration;
}
Log.d(BonusPackHelper.LOG_TAG, "Leg: " + startNodeIndex + "-" + endNodeIndex
+ ", length=" + length + "km, duration=" + duration + "s");
}
//--- Parcelable implementation
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeDouble(length);
out.writeDouble(duration);
out.writeInt(startNodeIndex);
out.writeInt(endNodeIndex);
}
public static final Parcelable.Creator<RoadLeg> CREATOR = new Parcelable.Creator<RoadLeg>() {
@Override
public RoadLeg createFromParcel(Parcel in) {
RoadLeg rl = new RoadLeg();
rl.length = in.readDouble();
rl.duration = in.readDouble();
rl.startNodeIndex = in.readInt();
rl.endNodeIndex = in.readInt();
return rl;
}
@Override
public RoadLeg[] newArray(int size) {
return new RoadLeg[size];
}
};
}

View File

@@ -1,84 +0,0 @@
package org.osmdroid.routing;
import java.util.ArrayList;
import org.oscim.core.GeoPoint;
import org.oscim.overlay.PathOverlay;
import org.oscim.view.MapView;
import android.content.Context;
import android.graphics.Paint;
/**
* Generic class to get a route between a start and a destination point, going
* through a list of waypoints.
*
* @see MapQuestRoadManager
* @see GoogleRoadManager
* @see OSRMRoadManager
* @author M.Kergall
*/
public abstract class RoadManager {
protected String mOptions;
public abstract Road getRoad(ArrayList<GeoPoint> waypoints);
public RoadManager() {
mOptions = "";
}
/**
* Add an option that will be used in the route request. Note that some
* options are set in the request in all cases.
*
* @param requestOption
* see provider documentation. Just one example:
* "routeType=bicycle" for MapQuest; "mode=bicycling" for Google.
*/
public void addRequestOption(String requestOption) {
mOptions += "&" + requestOption;
}
protected String geoPointAsString(GeoPoint p) {
StringBuffer result = new StringBuffer();
double d = p.getLatitude();
result.append(Double.toString(d));
d = p.getLongitude();
result.append("," + Double.toString(d));
return result.toString();
}
public static PathOverlay buildRoadOverlay(MapView mapView, Road road, Paint paint,
Context context) {
PathOverlay roadOverlay = new PathOverlay(mapView, 0, context);
roadOverlay.setPaint(paint);
if (road != null) {
ArrayList<GeoPoint> polyline = road.routeHigh;
for (GeoPoint p : polyline) {
roadOverlay.addPoint(p);
}
}
return roadOverlay;
}
/**
* Builds an overlay for the road shape with a default (and nice!) color.
*
* @param mapView
* ..
* @param road
* ..
* @param context
* ..
* @return route shape overlay
*/
public static PathOverlay buildRoadOverlay(MapView mapView, Road road, Context context) {
Paint paint = new Paint();
paint.setColor(0x800000FF);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
return buildRoadOverlay(mapView, road, paint, context);
}
}

View File

@@ -1,72 +0,0 @@
package org.osmdroid.routing;
import org.oscim.core.GeoPoint;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Road intersection, with instructions to continue.
*
* @author M.Kergall
*/
public class RoadNode implements Parcelable {
/**
* @see <a
* href="http://open.mapquestapi.com/guidance/#maneuvertypes">Maneuver
* Types</a>
*/
public int maneuverType;
/** textual information on what to do at this intersection */
public String instructions;
/** index in road links array - internal use only, for MapQuest directions */
public int nextRoadLink;
/** in km to the next node */
public double length;
/** in seconds to the next node */
public double duration;
/** position of the node */
public GeoPoint location;
public RoadNode() {
maneuverType = 0;
nextRoadLink = -1;
length = duration = 0.0;
}
// --- Parcelable implementation
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(maneuverType);
out.writeString(instructions);
out.writeDouble(length);
out.writeDouble(duration);
out.writeParcelable(location, 0);
}
public static final Parcelable.Creator<RoadNode> CREATOR = new
Parcelable.Creator<RoadNode>() {
@Override
public RoadNode createFromParcel(Parcel in) {
RoadNode rn = new RoadNode();
rn.maneuverType = in.readInt();
rn.instructions = in.readString();
rn.length = in.readDouble();
rn.duration = in.readDouble();
rn.location = in.readParcelable(GeoPoint.class.getClassLoader());
return rn;
}
@Override
public RoadNode[] newArray(int size) {
return new RoadNode[size];
}
};
}

View File

@@ -1,131 +0,0 @@
package org.osmdroid.utils;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import org.apache.http.NameValuePair;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
/**
* Useful functions and common constants.
*
* @author M.Kergall
*/
public class BonusPackHelper {
/** Log tag. */
public static final String LOG_TAG = "BONUSPACK";
/** User agent sent to services by default */
public static final String DEFAULT_USER_AGENT = "OsmBonusPack/1";
/**
* @return true if the device is the emulator, false if actual device.
*/
public static boolean isEmulator() {
//return Build.MANUFACTURER.equals("unknown");
return ("google_sdk".equals(Build.PRODUCT) || "sdk".equals(Build.PRODUCT));
}
/**
* @param connection
* ...
* @return the whole content of the http request, as a string
*/
private static String readStream(HttpConnection connection) {
String result = connection.getContentAsString();
return result;
}
/**
* sends an http request, and returns the whole content result in a String.
*
* @param url
* ...
* @return the whole content, or null if any issue.
*/
public static String requestStringFromUrl(String url) {
HttpConnection connection = new HttpConnection();
connection.doGet(url);
String result = readStream(connection);
connection.close();
return result;
}
/**
* requestStringFromPost: do a post request to a url with name-value pairs,
* and returns the whole content result in a String.
*
* @param url
* ...
* @param nameValuePairs
* ...
* @return the content, or null if any issue.
*/
public static String requestStringFromPost(String url, List<NameValuePair> nameValuePairs) {
HttpConnection connection = new HttpConnection();
connection.doPost(url, nameValuePairs);
String result = readStream(connection);
connection.close();
return result;
}
/**
* Loads a bitmap from a url.
*
* @param url
* ...
* @return the bitmap, or null if any issue.
*/
public static Bitmap loadBitmap(String url) {
Bitmap bitmap = null;
try {
InputStream is = (InputStream) new URL(url).getContent();
bitmap = BitmapFactory.decodeStream(new FlushedInputStream(is));
//Alternative providing better handling on loading errors?
/*
* Drawable d = Drawable.createFromStream(new
* FlushedInputStream(is), null); if (is != null) is.close(); if (d
* != null) bitmap = ((BitmapDrawable)d).getBitmap();
*/
} catch (Exception e) {
e.printStackTrace();
return null;
}
return bitmap;
}
/**
* Workaround on Android issue see
* http://stackoverflow.com/questions/4601352
* /createfromstream-in-android-returning-null-for-certain-url
*/
static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int byteValue = read();
if (byteValue < 0)
break; // we reached EOF
bytesSkipped = 1; // we read one byte
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
}

View File

@@ -1,153 +0,0 @@
package org.osmdroid.utils;
import java.util.ArrayList;
import org.oscim.core.GeoPoint;
/**
* Reduces the number of points in a shape using the Douglas-Peucker algorithm. <br>
* From:
* http://www.phpriot.com/articles/reducing-map-path-douglas-peucker-algorithm/4<br>
* Ported from PHP to Java. "marked" array added to optimize.
*
* @author M.Kergall
*/
public class DouglasPeuckerReducer {
/**
* Reduce the number of points in a shape using the Douglas-Peucker
* algorithm
*
* @param shape
* The shape to reduce
* @param tolerance
* The tolerance to decide whether or not to keep a point, in the
* coordinate system of the points (micro-degrees here)
* @return the reduced shape
*/
public static ArrayList<GeoPoint> reduceWithTolerance(ArrayList<GeoPoint> shape,
double tolerance)
{
int n = shape.size();
// if a shape has 2 or less points it cannot be reduced
if (tolerance <= 0 || n < 3) {
return shape;
}
boolean[] marked = new boolean[n]; //vertex indexes to keep will be marked as "true"
for (int i = 1; i < n - 1; i++)
marked[i] = false;
// automatically add the first and last point to the returned shape
marked[0] = marked[n - 1] = true;
// the first and last points in the original shape are
// used as the entry point to the algorithm.
douglasPeuckerReduction(
shape, // original shape
marked, // reduced shape
tolerance, // tolerance
0, // index of first point
n - 1 // index of last point
);
// all done, return the reduced shape
ArrayList<GeoPoint> newShape = new ArrayList<GeoPoint>(n); // the new shape to return
for (int i = 0; i < n; i++) {
if (marked[i])
newShape.add(shape.get(i));
}
return newShape;
}
/**
* Reduce the points in shape between the specified first and last index.
* Mark the points to keep in marked[]
*
* @param shape
* The original shape
* @param marked
* The points to keep (marked as true)
* @param tolerance
* The tolerance to determine if a point is kept
* @param firstIdx
* The index in original shape's point of the starting point for
* this line segment
* @param lastIdx
* The index in original shape's point of the ending point for
* this line segment
*/
private static void douglasPeuckerReduction(ArrayList<GeoPoint> shape, boolean[] marked,
double tolerance, int firstIdx, int lastIdx)
{
if (lastIdx <= firstIdx + 1) {
// overlapping indexes, just return
return;
}
// loop over the points between the first and last points
// and find the point that is the farthest away
double maxDistance = 0.0;
int indexFarthest = 0;
GeoPoint firstPoint = shape.get(firstIdx);
GeoPoint lastPoint = shape.get(lastIdx);
for (int idx = firstIdx + 1; idx < lastIdx; idx++) {
GeoPoint point = shape.get(idx);
double distance = orthogonalDistance(point, firstPoint, lastPoint);
// keep the point with the greatest distance
if (distance > maxDistance) {
maxDistance = distance;
indexFarthest = idx;
}
}
if (maxDistance > tolerance) {
//The farthest point is outside the tolerance: it is marked and the algorithm continues.
marked[indexFarthest] = true;
// reduce the shape between the starting point to newly found point
douglasPeuckerReduction(shape, marked, tolerance, firstIdx, indexFarthest);
// reduce the shape between the newly found point and the finishing point
douglasPeuckerReduction(shape, marked, tolerance, indexFarthest, lastIdx);
}
//else: the farthest point is within the tolerance, the whole segment is discarded.
}
/**
* Calculate the orthogonal distance from the line joining the lineStart and
* lineEnd points to point
*
* @param point
* The point the distance is being calculated for
* @param lineStart
* The point that starts the line
* @param lineEnd
* The point that ends the line
* @return The distance in points coordinate system
*/
public static double orthogonalDistance(GeoPoint point, GeoPoint lineStart, GeoPoint lineEnd)
{
double area = Math.abs(
(
1.0 * lineStart.latitudeE6 * lineEnd.longitudeE6
+ 1.0 * lineEnd.latitudeE6 * point.longitudeE6
+ 1.0 * point.latitudeE6 * lineStart.longitudeE6
- 1.0 * lineEnd.latitudeE6 * lineStart.longitudeE6
- 1.0 * point.latitudeE6 * lineEnd.longitudeE6
- 1.0 * lineStart.latitudeE6 * point.longitudeE6
) / 2.0
);
double bottom = Math.hypot(
lineStart.latitudeE6 - lineEnd.latitudeE6,
lineStart.longitudeE6 - lineEnd.longitudeE6
);
return (area / bottom * 2.0);
}
}

View File

@@ -1,170 +0,0 @@
package org.osmdroid.utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import android.util.Log;
/**
* A "very very simple to use" class for performing http get and post requests.
* So many ways to do that, and potential subtle issues. If complexity should be
* added to handle even more issues, complexity should be put here and only
* here. Typical usage:
*
* <pre>
* HttpConnection connection = new HttpConnection();
* connection.doGet(&quot;http://www.google.com&quot;);
* InputStream stream = connection.getStream();
* if (stream != null) {
* //use this stream, for buffer reading, or XML SAX parsing, or whatever...
* }
* connection.close();
* </pre>
*/
public class HttpConnection {
private DefaultHttpClient client;
private InputStream stream;
private HttpEntity entity;
private String mUserAgent;
private final static int TIMEOUT_CONNECTION = 3000; //ms
private final static int TIMEOUT_SOCKET = 8000; //ms
/**
* Constructor. Opens the url with an HttpURLConnection, then opens a stream
* on it. param sUrl : url to open
*/
public HttpConnection() {
stream = null;
entity = null;
HttpParams httpParameters = new BasicHttpParams();
/*
* useful? HttpProtocolParams.setContentCharset(httpParameters,
* "UTF-8"); HttpProtocolParams.setHttpElementCharset(httpParameters,
* "UTF-8");
*/
// Set the timeout in milliseconds until a connection is established.
HttpConnectionParams.setConnectionTimeout(httpParameters, TIMEOUT_CONNECTION);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
HttpConnectionParams.setSoTimeout(httpParameters, TIMEOUT_SOCKET);
client = new DefaultHttpClient(httpParameters);
//TODO: created here. Reuse to do for better perfs???...
}
public void setUserAgent(String userAgent) {
mUserAgent = userAgent;
}
public void doGet(String sUrl) {
HttpGet request = new HttpGet(sUrl);
if (mUserAgent != null)
request.setHeader("User-Agent", mUserAgent);
try {
HttpResponse response = client.execute(request);
StatusLine status = response.getStatusLine();
if (status.getStatusCode() != 200) {
Log.e(BonusPackHelper.LOG_TAG, "Invalid response from server: " + status.toString());
} else {
entity = response.getEntity();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void doPost(String sUrl, List<NameValuePair> nameValuePairs) {
HttpPost request = new HttpPost(sUrl);
if (mUserAgent != null)
request.setHeader("User-Agent", mUserAgent);
try {
request.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(request);
StatusLine status = response.getStatusLine();
if (status.getStatusCode() != 200) {
Log.e(BonusPackHelper.LOG_TAG, "Invalid response from server: " + status.toString());
} else {
entity = response.getEntity();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @return the opened InputStream, or null if creation failed for any
* reason.
*/
public InputStream getStream() {
try {
if (entity != null)
stream = entity.getContent();
} catch (IOException e) {
e.printStackTrace();
}
return stream;
}
/**
* @return the whole content as a String, or null if creation failed for any
* reason.
*/
public String getContentAsString() {
try {
if (entity != null) {
return EntityUtils.toString(entity, "UTF-8");
//setting the charset is important if none found in the entity.
}
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* Calling close once is mandatory.
*/
public void close() {
if (stream != null) {
try {
stream.close();
stream = null;
} catch (IOException e) {
e.printStackTrace();
}
}
if (entity != null) {
try {
entity.consumeContent();
//"finish". Important if we want to reuse the client object one day...
entity = null;
} catch (IOException e) {
e.printStackTrace();
}
}
if (client != null) {
client.getConnectionManager().shutdown();
client = null;
}
}
}

View File

@@ -1,22 +0,0 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.osmdroid.utils;
public class MathConstants {
public static final double PI180E6 = (Math.PI / 180) / 1000000.0;
public static final double PIx4 = Math.PI * 4;
}

View File

@@ -1,98 +0,0 @@
package org.osmdroid.utils;
import java.util.ArrayList;
import org.oscim.core.GeoPoint;
/**
* Methods to encode and decode a polyline with Google polyline
* encoding/decoding scheme. See
* https://developers.google.com/maps/documentation/utilities/polylinealgorithm
*/
public class PolylineEncoder {
private static StringBuffer encodeSignedNumber(int num) {
int sgn_num = num << 1;
if (num < 0) {
sgn_num = ~(sgn_num);
}
return (encodeNumber(sgn_num));
}
private static StringBuffer encodeNumber(int num) {
StringBuffer encodeString = new StringBuffer();
while (num >= 0x20) {
int nextValue = (0x20 | (num & 0x1f)) + 63;
encodeString.append((char) (nextValue));
num >>= 5;
}
num += 63;
encodeString.append((char) (num));
return encodeString;
}
/**
* Encode a polyline with Google polyline encoding method
*
* @param polyline
* the polyline
* @param precision
* 1 for a 6 digits encoding, 10 for a 5 digits encoding.
* @return the encoded polyline, as a String
*/
public static String encode(ArrayList<GeoPoint> polyline, int precision) {
StringBuffer encodedPoints = new StringBuffer();
int prev_lat = 0, prev_lng = 0;
for (GeoPoint trackpoint : polyline) {
int lat = trackpoint.latitudeE6 / precision;
int lng = trackpoint.longitudeE6 / precision;
encodedPoints.append(encodeSignedNumber(lat - prev_lat));
encodedPoints.append(encodeSignedNumber(lng - prev_lng));
prev_lat = lat;
prev_lng = lng;
}
return encodedPoints.toString();
}
/**
* Decode a "Google-encoded" polyline
*
* @param encodedString
* ...
* @param precision
* 1 for a 6 digits encoding, 10 for a 5 digits encoding.
* @return the polyline.
*/
public static ArrayList<GeoPoint> decode(String encodedString, int precision) {
ArrayList<GeoPoint> polyline = new ArrayList<GeoPoint>();
int index = 0;
int len = encodedString.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encodedString.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encodedString.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
GeoPoint p = new GeoPoint(lat * precision, lng * precision);
polyline.add(p);
}
return polyline;
}
}