So I've spent a good amount of time attempting to figure out how to speed this up, but I'm out of ideas now. I have a class, mapPopup in which a MapView is displayed over the entire screen. There is an array of an array of GeoPoint in mapPopup, and I want to draw lines between each GeoPoint in the 2nd dimensions of the array. I've accomplished this task already using a custom class, mapOverlay, that extends Overlay, but the problem I am having is that once all the map overlays are drawn, the map is extremely slow to zoom or pan. Once all the overlays are added to the map there are often over 2000, but they are all very small.
Thinking that the map would work more quickly if there were less overlays, I drew all the lines to three seperate overlays instead of a seperate overlay for each line. This actually resulted in SLOWER panning and zooming of the map, so I reverted back to the many small overlays.
I would appreciate some informative and easy to understand descriptions of a method that I could employ to make the map faster. Pseudocode or real code for the potential method would also help me to understand it better. My code is posted below. Once more, please note that my overlays and map display properly; I would just like a method that will allow faster panning and zooming.
mapOverlay class
public class mapOverlay extends Overlay {
private Projection projection;
private GeoPoint gp1;
private GeoPoint gp2;
private int color;
public mapOverlay(int color, MapView map, GeoPoint geo1, GeoPoint geo2) {
// super();
this.projection = map.getProjection();
this.gp1 = geo1;
this.gp2 = geo2;
this.color = color;
}
public void draw(Canvas canvas, MapView mapv, boolean shadow) {
super.draw(canvas, mapv, false);
Paint mPaint = new Paint();
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4);
mPaint.setColor(this.color);
Point p1 = new Point();
Point p2 = new Point();
Path path1 = new Path();
projection.toPixels(gp1, p1);
projection.toPixels(gp2, p2);
path1.moveTo(p1.x, p1.y);
path1.lineTo(p2.x, p2.y);
canvas.drawPath(path1, mPaint);
}
}
mapPopup class
public class mapPopup extends MapActivity {
public String[] trailNames;
public String tableName = "";
public int numTrails = 0;
public static GeoPoint[][] geoPoints;
public int[] colors = new int[] { Color.WHITE, Color.BLUE, Color.CYAN,
Color.RED, Color.YELLOW, Color.MAGENTA, Color.GRAY, Color.LTGRAY };
public int[] newColors;
// public Bitmap b;
public GeoPoint firstP;
public void loadMapData(Bitmap b, MapView map, int[] colors,
GeoPoint[][] GPAA, int ZoomLevel) {
// GPAA holds an array of an array of GeoPoint
Log.i("DEBUG", "starting loadMapDataTask");
map.setSatellite(true);
MapController mc = map.getController();
mapOverlay[][] mapOverlay = new mapOverlay[GPAA.length][];
Log.i("DEBUG", "length of GPAA is: " + GPAA.length);
// i cycles through the first dimension of GPAA
for (int i = 0; i < GPAA.length; i++) {
GeoPoint[] geoPoints = GPAA[i];
int length = geoPoints.length - 1;
mapOverlay[i] = new mapOverlay[length]; //
int pointCount = 0;
// z cycles through the second dimension of GPAA
for (int z = 0; z < length; z++) {
mapOverlay[i][z] = new mapOverlay(colors[i], map,
geoPoints[pointCount], geoPoints[pointCount + 1]);
pointCount++;
}
}
// Actually adds overlays to map
List<Overlay> mapOverlays = map.getOverlays();
for (int i = 0; i < mapOverlay.length; i++) {
int length = mapOverlay[i].length;
Log.i("DEBUG", "Adding map overlays for trail: " + i);
Log.i("DEBUG", "Length of mapOverlay[i] is: " + length);
for (int z = 0; z < length; z++) {
mapOverlays.add(mapOverlay[i][z]);
}
}
mc.animateTo(GPAA[0][0]);
mc.setZoom(ZoomLevel);
Rect r = new Rect();
map.getDrawingRect(r);
map.invalidate(r);
}
public static class runBGLoad extends
AsyncTask<bgLoadParam, Integer, GeoPoint[][]> {
public GeoPoint[][] geoPoints;
protected GeoPoint[] getGPa(Context context, String name, int ID) {
File file = context.getFileStreamPath(name);
if (file.exists() == false) {
Log.i("DEBUG", "Creating file");
InputStream is;
FileOutputStream fos;
try {
Log.i("DEBUG", "id is " + ID);
is = context.getResources().openRawResource(ID);
byte[] buffer = new byte[is.available()];
is.read(buffer);
fos = context.openFileOutput(name, Context.MODE_PRIVATE);
fos.write(buffer);
fos.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
} else {
Log.i("DEBUG", "File already exists");
}
// Log.i("DEBUG", "starting to get geopoints");
List<Location> gpsPoints = XMLParser.getPoints(file);
int i = 0;
int index = 0;
GeoPoint[] geoPoints = new GeoPoint[gpsPoints.size()];
// makes list of gpsPoints into GeoPoint[]
ListIterator<Location> it = gpsPoints.listIterator();
while (it.hasNext()) {
index = it.nextIndex();
Location loc = gpsPoints.get(index);
geoPoints[i] = new GeoPoint((int) (loc.getLatitude() * 1E6),
(int) (loc.getLongitude() * 1E6));
it.next();
i++;
}
return geoPoints;
}
#Override
protected GeoPoint[][] doInBackground(bgLoadParam... params) {
Context context = params[0].getContext();
int tNLength = params[0].getTNames().length;
geoPoints = new GeoPoint[tNLength][];
for (int i = 0; i < params[0].getTNames().length; i++) {
String modName = params[0].getTNames()[i].toLowerCase()
.replace(' ', '_');
int identifier = context.getResources().getIdentifier(modName,
"raw", context.getPackageName());
geoPoints[i] = getGPa(params[0].getContext(), modName
+ "_mapfile", identifier);
}
Log.i("DEBUG", "TEST");
mapPopup.geoPoints = geoPoints;
Log.i("DEBUG", "TEST2");
return geoPoints;
}
#Override
protected void onPostExecute(GeoPoint[][] result) {
Log.i("DEBUG", "The points are loaded.");
mapPopup.geoPoints = result;
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
Intent intent = getIntent();
String[] extras = intent.getStringArrayExtra("strings");
tableName = extras[1];
numTrails = Integer.parseInt(extras[2]);
trailNames = intent.getStringArrayExtra("trailNamesA");
super.onCreate(savedInstanceState);
setContentView(R.layout.map_popup_layout);
newColors = new int[numTrails];
for (int i = 0; i < numTrails; i++) {
newColors[i] = colors[i];
}
ViewGroup layout = (ViewGroup) findViewById(R.id.map_popup);
TextView[] tVs = new TextView[numTrails];
for (int i = 0; i < numTrails; i++) {
LayoutParams params = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
tVs[i] = new TextView(getApplicationContext());
tVs[i].setText(trailNames[i]);
tVs[i].setId(i + 700);
tVs[i].setTextColor(colors[i]);
tVs[i].setBackgroundColor(Color.BLACK);
if (i > 0) {
params.addRule(RelativeLayout.BELOW, (699 + i));
}
layout.addView(tVs[i], params);
}
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
MapView map = (MapView) findViewById(R.id.popupMV);
Bitmap b = Bitmap.createBitmap(map.getWidth(), map.getHeight(),
Bitmap.Config.RGB_565);
try {
trailsActivity.mapPreLoad.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
loadMapData(b, map, newColors, geoPoints, 17);
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}
I'm currently facing the same problematic, and I just found a workaround : prevent the overlays from drawing when zooming or panning. That's not perfect and I'm still looking for a better solution, but at least the map is usable without waiting 5 seconds for each pan or zoom.
Here is the code I used in my Overlay extension. It's not Java but C# (using Monodroid) - but it should be easily understandable.
public override bool OnTouchEvent (MotionEvent e, Android.GoogleMaps.MapView mapView)
{
if (e.Action == MotionEventActions.Down)
_mustDraw = false;
else if (e.Action == MotionEventActions.Up)
_mustDraw = true;
return base.OnTouchEvent (e, mapView);
}
public override void Draw (Android.Graphics.Canvas canvas, Android.GoogleMaps.MapView mapView, bool shadow)
{
if (shadow || !_mustDraw)
return;
// ...
}
That solution works for every map-touch based action, and now performs with a good speed, I just lack implementation of the same behaviour when zooming in or out using built-in zoom controls, but I first need to fight some of my bugs before doing this part, I'll come back on this part later.
Related
i have a situation in my app where i should move my map from one location to another location....i am quite new to android..and i found out how to draw a line in between two locations..
public class Mapview extends MapActivity implements LocationListener{
MapController mc;
GeoPoint p,p1,p2;
LocationManager lm;
String provider;
class Mapoverlay extends com.google.android.maps.Overlay
{
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
long when) {
// TODO Auto-generated method stub
super.draw(canvas, mapView, shadow);
Point screenpoints=new Point();
Point screenpoints1=new Point();
Point screenpoints2=new Point();
Paint paint;
paint = new Paint();
paint.setColor(Color.RED);
paint.setAntiAlias(true);
paint.setStyle(Style.FILL);
paint.setStrokeWidth(2);
paint.setAlpha(120);
Paint paint1;
paint1 = new Paint();
paint1.setColor(Color.BLUE);
paint1.setAntiAlias(true);
paint1.setStyle(Style.FILL);
paint1.setStrokeWidth(2);
paint1.setAlpha(120);
if(p != null)
{
mapView.getProjection().toPixels(p, screenpoints);
mapView.getProjection().toPixels(p1, screenpoints1);
mapView.getProjection().toPixels(p2, screenpoints2);
// Bitmap map=BitmapFactory.decodeResource(getResources(), R.drawable.pushpin1);
// canvas.drawBitmap(map, screenpoints.x, screenpoints.y-53, null);
canvas.drawLine(screenpoints.x,screenpoints.y,screenpoints1.x,screenpoints1.y, paint);
canvas.drawLine(screenpoints.x,screenpoints.y,screenpoints2.x,screenpoints2.y, paint);
}
return true;
}
}
#Override
protected void onCreate(Bundle icicle) {
// TODO Auto-generated method stub
super.onCreate(icicle);
setContentView(R.layout.mapview);
MapView map=(MapView)findViewById(R.id.mapView);
map.setBuiltInZoomControls(true);
mc=map.getController();
String[] coordinates={"51.4750766129036", "-3.15672342166522"};
double lat = Double.parseDouble(coordinates[0]);
double lng = Double.parseDouble(coordinates[1]);
p=new GeoPoint((int)(lat*1E6), (int)(lng*1E6));
String[] coordinates1={"17.453117" , "78.467586" };
double lat1 = Double.parseDouble(coordinates1[0]);
double lng1 = Double.parseDouble(coordinates1[1]);
p2=new GeoPoint((int)(lat1*1E6), (int)(lng1*1E6));
p1 = new GeoPoint(19240000,-99120000);
// p = new GeoPoint(19241000,-99121000);
lm=(LocationManager)getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
provider=lm.getBestProvider(criteria, true);
Location loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
List<String> lists=lm.getAllProviders();
// float f=loc.distanceTo(loc);
if (loc!=null){
System.out.println("Provider " + provider + " has been selected.");
onLocationChanged(loc);
}else{
Toast.makeText(getApplicationContext(), "Provider " + provider+ loc + lists+" has not been selected.", 5000).show();
// this.finish();
}
// Toast.makeText(getApplicationContext(), p.getLatitudeE6()+p.getLongitudeE6(), Toast.LENGTH_SHORT).show();
mc.animateTo(p);
mc.setZoom(1);
map.invalidate();
Mapoverlay mapOverlay = new Mapoverlay();
List<Overlay> listOfOverlays = map.getOverlays();
listOfOverlays.clear();
listOfOverlays.add(mapOverlay);
}
i am stuck at moving map from one location to another without user activity
for example:when the app initiates location of newyork city is shown then the map should move to texas ...any help willl be grateful
Try This class just pass Activity act,GeoPoint src,GeoPoint dest, int color, MapView mMapView
To call this class do this
new getRoute().DrawPath(this,mGeoPoint,getGeoPoint,Color.RED,mMapView);
public class getRoute
{
/*Variable*/
double mIntentLatitude, mIntentLongitude;
double mCursorLatitude, mCursorLongitude, mStartLatitude, mStartLongitude, mEndLatitude, MEndLongitude;
String mJsonData;
String mEnd_Address, mStart_Address, mName;
int mLength;
GeoPoint mGeoPoint = new GeoPoint(220328269, 725588202);
double mLatitude_End[], mLongitude_End[], mLatitude_Start[], mLongitude_Start[];
Activity activity;
public getRoute
(){
}
boolean error = false;
public void DrawPath(Activity act,GeoPoint src,GeoPoint dest, int color, MapView mMapView01)
{
// connect to map web service
DrawPathBack draw = new DrawPathBack(act, src, dest, color, mMapView01);
draw.execute("Draw");
}
public class DrawPathBack extends AsyncTask<String, Integer,Void>
{
ProgressDialog bar;
List<Overlay> mListOverlay;
MapOverlay mapOverlay;
ItemizedOverlay<OverlayItem> mItemizedOverlay;
GeoPoint src,dest;
int color;
MapView mMapView;
CommonMethod mCommonMethod;
String [] pairs;
String[] lngLat;
public DrawPathBack(Activity act,GeoPoint gpsrc,GeoPoint gpdest, int c, MapView mMap)
{
activity =act;
src=gpsrc;
dest=gpdest;
color = c;
mMapView=mMap;
mListOverlay = mMapView.getOverlays();
mapOverlay = new MapOverlay(mGeoPoint);
mListOverlay.add(mapOverlay);
mMapView.invalidate();
}
#Override
protected Void doInBackground(String... params)
{
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setSoTimeout(httpParameters, 60000);
HttpClient client = new DefaultHttpClient();
try {
HttpPost httpPost = new HttpPost("http://maps.googleapis.com/maps/api/directions/json?origin="+ (Double.toString((double)src.getLatitudeE6()/1.0E6)) + "," +(Double.toString((double)src.getLongitudeE6()/1.0E6 ) + "&destination=" + (Double.toString((double)dest.getLatitudeE6()/1.0E6)) + ","+ (Double.toString((double)dest.getLongitudeE6()/1.0E6))+ "&sensor=false"));
mIntentLatitude=((double)src.getLatitudeE6()/1.0E6);
mIntentLongitude=((double)src.getLongitudeE6()/1.0E6);
//httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse httpResponse = client.execute(httpPost);
mJsonData = EntityUtils.toString(httpResponse.getEntity());
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Integer... progress)
{
bar.setMessage("Time Progress "+progress[0]);
}
#Override
protected void onPostExecute(Void result)
{
try {
JSONObject jsonObj = new JSONObject(mJsonData);
// grabbing the routes object
JSONArray routes = jsonObj.getJSONArray("routes");
for (int i = 0; i < routes.length(); i++) {
JSONObject rout = routes.getJSONObject(i);
JSONObject bounds = rout.getJSONObject("bounds");
JSONObject northest = bounds.getJSONObject("northeast");
mStartLatitude = northest.getDouble("lat");
mStartLongitude = northest.getDouble("lng");
JSONObject southwest = bounds.getJSONObject("southwest");
mEndLatitude = southwest.getDouble("lat");
MEndLongitude = southwest.getDouble("lng");
System.out.println("get data from jeson" + mCursorLatitude + mCursorLongitude + mEndLatitude
+ MEndLongitude);
// grabbing the routes legs
JSONArray legs = rout.getJSONArray("legs");
System.out.println("length of legs array " + legs.length());
for (int j = 0; j < legs.length(); j++) {
JSONObject leg = legs.getJSONObject(j);
System.out.println("enter in second array");
JSONObject distance = leg.getJSONObject("distance");
String mTextDistent = distance.getString("text");
System.out.println("distances bitween two point" + mTextDistent);
JSONObject duration = leg.getJSONObject("duration");
String mTextDurestion = duration.getString("text");
mEnd_Address = leg.getString("end_address");
mStart_Address = leg.getString("start_address");
System.out.println("get data from jeson in second arry"
+ mTextDurestion + " " + mEnd_Address + " " + mStart_Address);
JSONArray step = leg.getJSONArray("steps");
mLength = step.length();
mLatitude_End = new double[mLength];
mLongitude_End = new double[mLength];
mLatitude_Start = new double[mLength];
mLongitude_Start = new double[mLength];
for (int k = 0; k < step.length(); k++) {
JSONObject st = step.getJSONObject(k);
System.out.println("enter in third array");
JSONObject end_lo = st.getJSONObject("end_location");
JSONObject start_lo = st
.getJSONObject("start_location");
mLatitude_End[k] = end_lo.getDouble("lat");
mLongitude_End[k] = end_lo.getDouble("lng");
mLatitude_Start[k] = start_lo.getDouble("lat");
mLongitude_Start[k] = start_lo.getDouble("lng");
}
for (int mDistanse = 0; mDistanse < mLength; mDistanse++) {
System.out.println("end location let" + mLatitude_End[mDistanse]);
System.out.println("end location long+"
+ mLongitude_End[mDistanse]);
System.out.println("Start location let"
+ mLatitude_Start[mDistanse]);
System.out.println("Start location long"
+ mLongitude_Start[mDistanse]);
}
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
public class MapOverlay extends com.google.android.maps.Overlay {
public MapOverlay(GeoPoint mGeoPoint) {
}
#Override
public boolean draw(final Canvas canvas, MapView mapView,
boolean shadow, long when) {
Point mpoint = new Point();
Point mpoint1 = new Point();
int let[] = new int[mLength];
int lon[] = new int[mLength];
int let_end[] = new int[mLength];
int lon_end[] = new int[mLength];
GeoPoint newGeoPoint = null;
GeoPoint newGeoPoint1;
for (int k = 0; k < mLength; k++) {
let[k] = (int) (mLatitude_Start[k] * 1E6);
lon[k] = (int) (mLongitude_Start[k] * 1E6);
let_end[k] = (int) (mLatitude_End[k] * 1E6);
lon_end[k] = (int) (mLongitude_End[k] * 1E6);
newGeoPoint1 = new GeoPoint(let_end[k], lon_end[k]);
newGeoPoint = new GeoPoint(let[k], lon[k]);
mapView.getProjection().toPixels(newGeoPoint, mpoint);
mapView.getProjection().toPixels(newGeoPoint1, mpoint1);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeWidth(5);
canvas.drawCircle(mpoint.x, mpoint.y, 5, paint);
paint.setColor(Color.BLUE);
canvas.drawLine(mpoint.x, mpoint.y, mpoint1.x, mpoint1.y, paint);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(100);
paint.setStyle(Paint.Style.FILL);
if(k==mLength-1){
Bitmap bmp = BitmapFactory.decodeResource(activity.getResources(), R.drawable.green_pin);
canvas.drawBitmap(bmp,mpoint1.x ,mpoint1.y-30, null);
}
GeoPoint dumy=new GeoPoint((int)(mIntentLatitude * 1E6), (int)(mIntentLongitude * 1E6));
Point dumy1 = new Point();
mapView.getProjection().toPixels(dumy, dumy1);
Bitmap bmp = BitmapFactory.decodeResource(activity.getResources(), R.drawable.dest_pin);
canvas.drawBitmap(bmp,dumy1.x,dumy1.y - 25, null);
mapView.getController().animateTo(dumy);
mapView.invalidate();
}
return false;
}
}
}
Try this if you want to move map on particular position then get lat or long of that position and just pass in this :
MapController mMapController;
mMapController=mMapView.getController();
mMapController.setCenter(new GeoPoint((int)(lat * 1E6), (int)(lon * 1E6)));
and if you want to draw path between two location then just pass lat and lon in this :
Intent intent = new Intent(android.content.Intent.ACTION_VIEW,
Uri.parse("http://maps.google.com/maps?saddr="+ String.valueOf(from_lattitude) +","+ String.valueOf(from_longitude) +"&daddr="+ String.valueOf(dest_lati) +","+ String.valueOf(dest_longi)));
startActivity(intent);
So I have my mapview set up, and everything runs, but the overlays don't show up on the map. Any suggestions or help at all would be greatly appreciated.
My MapActivity extension class is the following:
public class trailInformation extends MapActivity {
public String trailName = "";
public loadMapDataTask mapTask = new loadMapDataTask();
public myObject inp = new myObject();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.trail_info_layout);
// General variable declarations
Intent intent = getIntent();
trailName = intent.getStringExtra(trailsActivity.EXTRA_MESSAGE);
// Sets map to satellite
final MapView map = (MapView) findViewById(R.id.infoMapView);
map.setSatellite(true);
// Setup map input
inp.setID(R.raw.nordhoff_peak_loop);
inp.setName("mapfile");
inp.setMap(map);
// Display Trail Name
Typeface font = Typeface.createFromAsset(getAssets(), "arial.ttf");
TextView trailNameTV = (TextView) findViewById(R.id.infoTitle);
trailNameTV.setText(trailName);
trailNameTV.setTypeface(font);
Display display = getWindowManager().getDefaultDisplay();
trailNameTV.setTextSize(findTextSize(trailNameTV, trailName,
GalleryPageActivity.getDisplaySize(display).x, font));
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
mapTask.execute(inp);
}
public class loadMapDataTask extends AsyncTask<myObject, Void, File> {
#Override
protected File doInBackground(myObject... params) {
File file = getApplicationContext().getFileStreamPath(
params[0].getName());
if (file.exists()) {
return file;
}
InputStream is;
FileOutputStream fos;
try {
is = getResources().openRawResource(params[0].getID());
byte[] buffer = new byte[is.available()];
is.read(buffer);
fos = openFileOutput(params[0].getName(), MODE_PRIVATE);
fos.write(buffer);
fos.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
List<Location> gpsPoints = XMLParser.getPoints(file);
int i = 0;
int index = 0;
GeoPoint[] geoPoints = new GeoPoint[gpsPoints.size()];
ListIterator<Location> it = gpsPoints.listIterator();
while (it.hasNext()) {
index = it.nextIndex();
Location loc = gpsPoints.get(index);
geoPoints[i] = new GeoPoint((int) (loc.getLatitude() * 1E6),
(int) (loc.getLongitude() * 1E6));
it.next();
Log.i("DEBUG", "" + geoPoints[i]);
}
if (geoPoints.length > 1) {
mapOverlay[] overlays = new mapOverlay[(geoPoints.length - 1)];
MapController mc = params[0].getMap().getController();
mc.animateTo(geoPoints[0]);
mc.setZoom(17);
for (int z = 0; z < overlays.length; z++) {
List<Overlay> mapOverlays;
mapOverlays = params[0].getMap().getOverlays();
mapOverlays.add(overlays[z]);
}
} else {
Log.i("DEBUG", "Not drawing lines because " + geoPoints.length
+ " points exist in geopoints array.");
}
return file;
}
#Override
protected void onPostExecute(File result) {
Log.i("DEBUG", "Task executed");
}
}
public static String readRawTextFile(Context ctx, int resId) {
InputStream inputStream = ctx.getResources().openRawResource(resId);
InputStreamReader inputreader = new InputStreamReader(inputStream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line;
StringBuilder text = new StringBuilder();
try {
while ((line = buffreader.readLine()) != null) {
text.append(line);
text.append('\n');
}
} catch (IOException e) {
return null;
}
return text.toString();
}
public float findTextSize(TextView tV, String text, float Width,
Typeface font) {
float textSize = 100;
float scaledPx = 0;
float densityMultiplier = getBaseContext().getResources()
.getDisplayMetrics().density;
TextPaint paint = tV.getPaint();
paint.setTypeface(font);
while (textSize > 20) {
scaledPx = textSize * densityMultiplier;
paint.setTextSize(scaledPx);
if (paint.measureText(text) < Width) {
return textSize;
} else {
textSize--;
}
}
return 0;
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}
And my mapOverlay class is the following:
public class mapOverlay extends Overlay {
private Projection projection;
public mapOverlay(MapView map) {
super();
projection = map.getProjection();
}
public void draw(Canvas canvas, MapView mapv, boolean shadow, GeoPoint gp1,
GeoPoint gp2) {
super.draw(canvas, mapv, shadow);
// Configuring the paint brush
Paint mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4);
Point p1 = new Point();
Point p2 = new Point();
Path path1 = new Path();
projection.toPixels(gp1, p1);
projection.toPixels(gp2, p2);
path1.moveTo(p1.x, p1.y);
path1.lineTo(p2.x, p2.y);
canvas.drawPath(path1, mPaint);
}
}
I think I might just be missing something about MapView, and there also might be a problem with my Asynctask since it's my first time using it, but I don't think there is.
I am working with a custom MapView for an application. I have a database with a LOT of GPS datapoints saved and I am currently loading them using Overlays, then performing an .addAll on the MapView with the Overlays.
However, it is taking up to 2 minutes to load just a few hundred data points as a path on the MapView.
The code to load the Data Points is:
private void loadMap() {
//Load the specific data from the database
DBAdapter db = new DBAdapter(this);
try {
db.open();
Cursor mDataPoints = db.db.rawQuery("SELECT * FROM GPS_DATA)", null);
if ((mDataPoints != null) && (!mDataPoints.isClosed()) && (mDataPoints.moveToFirst())) {
mapMain.setFinishedLoading(false);
mapMain.getOverlays().clear();
if ((!mDataPoints.isClosed()) && (mDataPoints.moveToFirst())) {
while (!mDataPoints.isAfterLast()) {
this.drawPath(db,
DBAdapter.formatLong(mDataPoints, "data_id"),
DBAdapter.formatString(mDataPoints, "data_name"),
DBAdapter.formatString(mDataPoints, "data_type"));
mDataPoints.moveToNext();
}
}
mapMain.refreshDrawableState();
mapMain.setEnabled(true);
}
} finally {
db.close();
}
}
public void drawPath(DBAdapter db, long pDataID, String pDataName, String pDataType) {
Cursor mData = db.getPointDataByDataID(pDataID);
if ((!mData.isClosed()) && (mData.moveToFirst())) {
boolean vFirst = true;
int i = 0;
GeoPoint startGP;
GeoPoint geoPoint1;
GeoPoint geoPoint2 = null;
while (!mData.isAfterLast()) {
if (vFirst) {
startGP = new GeoPoint((int) (DBAdapter.formatDouble(mData, "latitude") * 1E6), (int) (DBAdapter.formatDouble(mData, "longitude") * 1E6));
mapMain.getOverlays().add(new Map_Route_Overlay(startGP, startGP, this.returnPathColor(pDataType), pDataName));
vFirst = false;
geoPoint2 = startGP;
} else {
geoPoint1 = geoPoint2;
geoPoint2 = new GeoPoint((int) (DBAdapter.formatDouble(mData, "latitude") * 1E6), (int) (DBAdapter.formatDouble(mData, "longitude") * 1E6));
if (geoPoint2.getLatitudeE6() != 22200000) {
mapMain.getOverlays().add(new Map_Route_Overlay(geoPoint1, geoPoint2, this.returnPathColor(pDataType), pDataName));
}
}
i += 1;
mData.moveToNext();
}
if (geoPoint2 != null) {
mapMain.getOverlays().add(new Map_Route_Overlay(geoPoint2, geoPoint2, this.returnDataColor(pDataType), pDataName));
}
}
mData.close();
}
public int returnDataColor(String pType) {
int vReturnData = Color.BLUE;
if (pType.trim().equals("S")) {
vReturnData = Color.RED;
}
return vReturnData;
}
And the code for the Map_Route_Overlay class is:
public final class Map_Route_Overlay extends Overlay {
private static String TAG = CoreFunctions.APP_TAG + "_MapRouteOverlay";
private GeoPoint geoPoint1;
private GeoPoint geoPoint2;
private int defaultColor = 999;
private String dataName = "";
public Map_Route_Overlay(GeoPoint pGeoPoint1, GeoPoint pGeoPoint2, int pColor, String pText) {
this.geoPoint1 = pGeoPoint1;
this.geoPoint2 = pGeoPoint2;
this.defaultColor = pColor;
this.dataName = pText;
}
public void setDataName(String pName) {
this.dataName = pName;
}
#Override
public boolean draw (Canvas canvas, MMMapView mapView, boolean shadow, long when) {
Projection projection = mapView.getProjection();
if (shadow == false) {
Paint paint = new Paint();
paint.setAntiAlias(true);
Point point = new Point();
projection.toPixels(this.geoPoint1, point);
paint.setColor(this.defaultColor);
Point point2 = new Point();
projection.toPixels(this.geoPoint2, point2);
paint.setStrokeWidth(2);
paint.setAlpha(this.defaultColor == Color.parseColor("#6C8715")?220:120);
canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);
}
return super.draw(canvas, mapView, shadow, when);
}
}
I have tried several options, including loading the data using Threads, but notifying the MapView to load the Overlays when completed was becoming a nightmare.
Just for reference, MMMapView is my custom MapView component, which for now just inherits MapView and implements two functions.
You really shouldn't be trying to display hundreds of Overlays on the screen at once, because you will get bad performance. Try limiting it to 10-20. Any more than that and it is too busy for the user anyway.
Also you should be using a thread to load the items from your database. What I do is I use a custom ItemizedOverlay, and add custom OverlayItems to it in a thread. Then once I am done loading I call mapView.postInvalidate(); so that they are displayed on the screen.
I am using this: http://code.google.com/p/mapview-overlay-manager/
It provides LazyLoading to load only the visible markers on the map.
Hi iam displaying mulitple markers in google map in android.while iam displaying, the markers are displaying in the google map one by one.Here i want to display more than 50 markers.But according to my code the markers are displaying one by one and to display 50 markers it is taking so much time.Below is my code which is in the same class.Any idea is appreciated.
public void displayMarkersOnMap(){
Runnable r=new Runnable(){
public void run(){
for (int i = 0; i < vector.size(); i++) {
try {
pinHM = (HashMap<String, Object>)vector.get(i);
mapView = (MapView)findViewById(R.id.mapView);
mapView.getController().setZoom(9);
Drawable marker;
else{
String status = pinHM.get("status").toString();
if (status.equals("ST_COMPLETE")) {
marker = getResources().getDrawable(R.drawable.pin_green);
}else if (status.equals("ST_IN_PROGRESS")) {
marker = getResources().getDrawable(R.drawable.pin_orange);
}else {
marker = getResources().getDrawable(R.drawable.pin_gray);
}
}
marker.setBounds((int) (-marker.getIntrinsicWidth() / 2),-marker.getIntrinsicHeight(),(int) (marker.getIntrinsicWidth() / 2), 0);
double latitude=Double.parseDouble(pinHM.get("latitude").toString());
double longitude=Double.parseDouble(pinHM.get("longitude").toString());
Geocoder geoCoder = new Geocoder(BaseMapActivity.this, Locale.getDefault());
List<Address> addresses = geoCoder.getFromLocationName(address,5);
if (addresses.size() > 0) {
GeoPoint point = new GeoPoint((int)(latitude*1E6),(int)(longitude*1E6));
funPlaces = new MyItemizedOverlay(point,marker,hmtostring,nameaddress,mapView);
mapView.getOverlays().add(funPlaces);
GeoPoint pt = funPlaces.getCenterPt();
int latSpan = funPlaces.getLatSpanE6();
int lonSpan = funPlaces.getLonSpanE6();
Log.v("Overlays", "Lat span is " + latSpan);
Log.v("Overlays", "Lon span is " + lonSpan);
MapController mc = mapView.getController();
mc.setCenter(pt);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}//end of run
};//end of Runnable
Thread thread = new Thread(r, "BaseMapActiviy");
thread.start();
}
public class MyItemizedOverlay extends BalloonItemizedOverlay {
private ArrayList<OverlayItem> m_overlays = new ArrayList<OverlayItem>();
#SuppressWarnings("unused")
private Context c;
private GeoPoint center = null;
public MyItemizedOverlay(GeoPoint point, Drawable marker,String hmtostring,String nameaddress,MapView mapView) {
super(boundCenter(marker), mapView);
c = mapView.getContext();
m_overlays.add(new OverlayItem(point,hmtostring,nameaddress));
populate();
}
public GeoPoint getCenterPt() {
if (center == null) {
int northEdge = -90000000;
int southEdge = 90000000;
int eastEdge = -180000000;
int westEdge = 180000000;
Iterator<OverlayItem> iter = m_overlays.iterator();
while (iter.hasNext()) {
GeoPoint pt = iter.next().getPoint();
if (pt.getLatitudeE6() > northEdge)
northEdge = pt.getLatitudeE6();
if (pt.getLatitudeE6() < southEdge)
southEdge = pt.getLatitudeE6();
if (pt.getLongitudeE6() > eastEdge)
eastEdge = pt.getLongitudeE6();
if (pt.getLongitudeE6() < westEdge)
westEdge = pt.getLongitudeE6();
}
center = new GeoPoint((int) ((northEdge + southEdge) / 2),
(int) ((westEdge + eastEdge) / 2));
}
return center;
}
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
if (!shadow) {
super.draw(canvas, mapView, shadow);
}
return false;
}
public void addOverlay(OverlayItem overlay) {
m_overlays.add(overlay);
populate();
}
#Override
protected OverlayItem createItem(int i) {
return m_overlays.get(i);
}
#Override
public int size() {
return m_overlays.size();
}
#Override
protected boolean onBalloonTap(int index) {
return true;
}
}
I just went through this myself. For your specific case define a new OverlayItem (not MyItemizedOverlay) with whatever then just add it to MyItemizedOverlay.
For your case it would be something like this.
OverlayItem anotherFunPlace = new OverlayItem(theGeoPointYouWantItAt,"Some string","Another String");
//Then you would use the following to add it
FunPlaces.add(anotherFunPlace);
Make sure to place those above lines before
mapView.getOverlays().add(funPlaces);
Hope that helps. Let me know if I missed something or if you have other problems.
newbie, I have class:
class PolyOverlay extends Overlay {
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow)
{
try {
List<GeoPoint> points = new ArrayList<GeoPoint>();
GeoPoint tmpPoint;
double lat2;
double lng2;
String args[] = {"",""};
args = sitesList.getpolyLine().get(daI).split("\\;");
//Toast.makeText(getApplicationContext(),"T: " + args[0],Toast.LENGTH_SHORT ).show();
for (int i = 0; i < args.length; i++) {
String coordinates2[] = {"",""};
String args2[] = {"",""};
args2 = args[i].split("\\,");
coordinates2[0]= args2[0];
coordinates2[1]= args2[1];
//Toast.makeText(getApplicationContext(),"T: " + coordinates2[0],Toast.LENGTH_SHORT ).show();
lat2= Double.parseDouble(coordinates2[0]);
lng2= Double.parseDouble(coordinates2[1]);
tmpPoint = new GeoPoint((int) (lat2 * 1E6), (int) (lng2 * 1E6) );
points.add(tmpPoint);
}
//for(Polygon polygonTemp : polygonList)
//{
Path p = new Path();
Projection projection = mapView.getProjection();
boolean firstTime = true;
for(GeoPoint geoPoint : points)
{
Point drawPoint = new Point();
projection.toPixels(geoPoint, drawPoint);
if(firstTime)
{
p.moveTo(drawPoint.x, drawPoint.y);
firstTime = false;
}
else
{
p.lineTo(drawPoint.x, drawPoint.y);
}
}
p.setFillType(Path.FillType.EVEN_ODD);
Paint polyPaint = new Paint();
polyPaint.setStrokeWidth(1);
polyPaint.setStyle(Paint.Style.FILL_AND_STROKE);
polyPaint.setAntiAlias(true);
polyPaint.setColor(Color.BLUE);
polyPaint.setAlpha(30);
canvas.drawPath(p, polyPaint);
firstTime = true;
//}
super.draw(canvas, mapView, shadow);
} catch (Exception e) {
Toast.makeText(epapp.this, "Err: " + e, Toast.LENGTH_LONG).show();
}
}
}
Then inside an xml loop I do this:
for (int i = 0; i < sitesList.getStrap().size(); i++) {
//icons
String pargs[] = sitesList.getCentr().get(i).split("\\,");
String coordinates3[] = {"",""};
coordinates3[0] = pargs[0].toString();
coordinates3[1] = pargs[1].toString();
//Toast.makeText(epapp.this, "Center: " + coordinates3[0], Toast.LENGTH_LONG).show();
double lat2 = Double.parseDouble(coordinates3[0]);
double lng2 = Double.parseDouble(coordinates3[1]);
np = new GeoPoint(
(int) (lat2 * 1E6),
(int) (lng2 * 1E6));
Drawable drawable = this.getResources().getDrawable(R.drawable.iconresidential);
IconItemizedOverlay itemizedoverlay = new IconItemizedOverlay(drawable,this);
OverlayItem overlayitem = new OverlayItem(np, "Property Information", "JONES EMERSON ROBERT JR & SARA MARIA<br>1032 Briarwood Dr Wauchula 33873<br>HARDEE County<br>STRAP 05-34-25-0865-00001-0020");
itemizedoverlay.addOverlay(overlayitem);
mapView.getOverlays().add(itemizedoverlay);
//if (i==1){
//polyString = sitesList.getpolyLine().get(i);
daI=i;
//polygon
PolyOverlay myPolyOverlay = new PolyOverlay();
mapView.getOverlays().add(myPolyOverlay);
//}
}
ok so the "problem" is if I do the //if (i==1){ part in the loop where "daI" is being set to "i", my "Polygon" is displayed on the map for that item in the XML, if I "REM" it out, the Polygon(s) overlay are always the last item in the XML. The xml list has 20 items in the list always and it seems as if the the "daI" variable is always 19 (last index in the list 0-19)
Obviously not do something so the PolyOverlay class gets "finished" before the xml loop is done?? It like the xml loop flys through sets "daI" to the last one and the PolyOverlay is loading the polygon for that last item...
My icons are just fine btw on the map...
k, I'm retarded: I had to do this:
int di = 0;
PolyOverlay(int n) {
di = n;
}
in my PolyOvelay class then pass the "i" from the xml for loop to it...
PolyOverlay myPolyOverlay = new PolyOverlay(i);
mapView.getOverlays().add(myPolyOverlay);