I am trying to show the users current location with the default blue dot in android. In my maps page I also have a layout that shows different points of interest. Im having trouble figuring out what to put for some of the variables and was wondering if someone could help me out.
This is what I'm using so far to show my location.
Location location = locationManager
.getLastKnownLocation(bestProvider);
try {
GeoPoint myPoint2 = new GeoPoint(
(int) (location.getLatitude() * 1E6),
(int) (location.getLongitude() * 1E6));
newoverlay.drawMyLocation(null, mapView, location, myPoint2,
1000);
mapOverlays.add(newoverlay);
} catch (NullPointerException e) {
GeoPoint myPoint2 = new GeoPoint((int) (-1 * 1E6),
(int) (-1 * 1E6));
**newoverlay.drawMyLocation(null, mapView, location, myPoint2,
1000);**
mapOverlays.add(newoverlay);
}
I'm not sure what to put as the Canvas so I placed it with null so that it would compile. I'm using the location from a location Manager and I have my geopoint from the location variable. I'm also unsure what the "when" parameter is supposed to be.
I was also wondering how the blue bubble knows to move with the person, does the picture update every x milliseconds depending on the "when" parameter?
So far the app isn't crashing, but it is also not showing the blue dot at any location.
I'm sure I just need help with finding what the canvas parameter should be.
Thanks
try this way in your map activity
class CurOverlay extends Overlay {
private GeoPoint pointToDraw;
public void setPointToDraw(GeoPoint point) {
pointToDraw = point;
}
public GeoPoint getPointToDraw() {
return pointToDraw;
}
#Override
public boolean draw(Canvas canvas, MapView curmapView, boolean shadow,
long when) {
super.draw(canvas, curmapView, shadow);
// convert point to pixels
Point screenPts = new Point();
curmapView.getProjection().toPixels(pointToDraw, screenPts);
// add marker
Bitmap bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.pinsource);
canvas.drawBitmap(bmp, screenPts.x - 28, screenPts.y - 48, null);
return true;
}
}
i hope this will work for you.
Related
I'm developing an Android aplication that has to show some "places of interest" on a mapview, along with the device current location. This works well.
Also, in my app, the user could "tap" a "place of interest" marker and the aplication would have to draw a route to that marker.
I used Google Directions api to get the route, along with a polyline decoder to get the GeoPoints between the user and the place. For my testing route, google gives me about 200 different GeoPoints.
So, I have a class like this to add those GeoPoints:
public class RouteOverlay extends Overlay {
private GeoPoint gp1;
private GeoPoint gp2;
private int color;
public RouteOverlay(GeoPoint gp1, GeoPoint gp2, int color) {
this.gp1 = gp1;
this.gp2 = gp2;
this.color = color;
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
Projection projection = mapView.getProjection();
Paint paint = new Paint();
Point point = new Point();
projection.toPixels(gp1, point);
paint.setColor(color);
Point point2 = new Point();
projection.toPixels(gp2, point2);
paint.setStrokeWidth(5);
paint.setAlpha(120);
canvas.drawLine(point.x, point.y, point2.x, point2.y, paint);
super.draw(canvas, mapView, shadow);
}
}
what I do to draw the route is the following:
1) Detect the onClick event to a marker in the map.
2) From that event, I create a new thread, where I make the call to the Google API.
3) Once I have the result, I parse/convert it in a GeoPoint list.
4) Then I call my drawPath method:
private void drawPath(List<GeoPoint> geoPoints, int color) {
mapOverlays.clear();
mapOverlays.add(myLocationOverlay);
mapOverlays.add(itemizedoverlay);
for (int i = 1; i < geoPoints.size(); i++) {
mapOverlays.add(new RouteOverlay(geoPoints.get(i - 1), geoPoints.get(i), color));
}
mapView.postInvalidate();
5) Finally, I return to the UI thread.
This method clears the map overlay list (mapOverlays). Then, adds to the list the current location and the "places of interest" overlays. And, finally, adds the route overlays.
The problem is that, suddenly, works veeery slow and finally crashes. But there is no message in the LogCat. So, I thought that 30 overlays + 1 + more than 200 for the route are too much for the phone to handle. But the tutorials I've seen do it this way so...
Can someone tell me if I do anything wrong?
Thanks in advance.
I figured out what I was doing wrong.
When I called the drawPath function, after obtaining the List of GeoPoints, I made a loop to check the coordinates of each point. Something like
for (int i = 0; i < geoList.size(); i++){
Log.i("GEOPOINT " + i, geoList.get(i).toString());
drawpath(geoList, Color.BLUE);
}
The drawPath function got called N times. So the device crashed. My fault.
Programming at 2:00 am is not good for the code!
I have list of stores and when i click on any one depending on their latitude and longitude values which i get from a web server i show them on the map. some of them show up but some wont...i know this is not a good question....but i am just expecting if someone who might have experienced the same problem might help.
here is the code:
Double Storelat = (FeedListViewActivity.lat);
Double Storelng = (FeedListViewActivity.lng);
storeLocation = new GeoPoint((int) (Storelat * 1E6), (int) (Storelng * 1E6));
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow);
Point locationPoint1 = new Point();
Projection projection1 = mapView.getProjection();
projection1.toPixels(storeLocation, locationPoint1);
Paint containerPaint = new Paint();
containerPaint.setAntiAlias(true);
int containerX1 = locationPoint1.x;
int containerY1 = locationPoint1.y;
if (shadow) {
containerX1 += CONTAINER_SHADOW_OFFSET;
containerY1 += CONTAINER_SHADOW_OFFSET;
containerPaint.setARGB(90, 0, 0, 0);
canvas.drawCircle(containerX1, containerY1, CONTAINER_RADIUS,
containerPaint);
} else {
containerPaint.setColor(Color.RED);
canvas.drawCircle(containerX1, containerY1, CONTAINER_RADIUS,
containerPaint);
}
}
and these are the values i get from the webserver:
working:
lat = 18.5170002
lng = 73.858078
not working:
lat = 18.618679
lng = 73.8037491
your answer is in your question itself
working:
lat = 18.5170002 lng = 73.858078
not working:
lat = 18.618679 lng = 73.8037491
as per above provided thing you can see the precision difference i have also faced the same problem be 6 months, and i have made that 6 precision to 8 precision and was working well then.
if you pass 18.618679 then it will treat it as 0.18618679 for confirmation try to zoom out up-to level 2 or 3 you will get your point at unexpected place.
I am using OsmDroid for my Android application. I am setting a IGeoPoint as follows
IGeoPoint point2 = new IGeoPoint() {
public int getLongitudeE6() {
return 51475022;
}
public int getLatitudeE6() {
return -300322;
}
};
mapController.animateTo(point2);
this took me to deep blue sea. Whereas when I use google.mapview and set geopoint in following way
myMapController.animateTo(new GeoPoint((int) (51.475022 * 1E6),
(int) (-0.300322 * 1E6)));
it takes me to where I want
What's wrong with osmdroid?
Why are you trying to create a constructor for an Interface?
The Osmdroid GeoPoint is a class which implements this interface. You just need to instantiate a GeoPoint, like this:
GeoPoint gPt = new GeoPoint(51500000, -150000); // latitude, longitude
Then pass this to your .animate()
I'm just trying to make sense of a basic Android navigation-related question, namely "How can I display the current location". I've used a bit of code from articles and tutorials from my long googling sessions. The display of a simple overlay (circle + text message) is works, yet at a wrong on-screen position (on the Equator apparently).
My code setup includes a small inner class that implements LocationListener, and its onLocationChanged event handler calls this method :
protected void createAndShowCustomOverlay(Location newLocation)
{
double lat = newLocation.getLatitude();
double lng = newLocation.getLongitude();
// geoPointFromLatLng is an E6 converter :
// return new GeoPoint((int) (pLat * 1E6), (int) (pLng * 1E6));
GeoPoint geopoint = GeoFunctions.geoPointFromLatLng(lat, lng);
CustomOverlay overlay = new CustomOverlay(geopoint);
mapView.getOverlays().add(overlay);
mapView.getController().animateTo(geopoint);
mapView.postInvalidate();
}
Up to this point, it all looks ok, I've debugged around and the non-transformed lat/lng pair is ok, the E6 variant thereof ok as well. Here is the CustomOverlay class :
public class CustomOverlay extends Overlay
{
private static final int CIRCLERADIUS = 2;
private GeoPoint geopoint;
public CustomOverlay(GeoPoint point)
{
geopoint = point;
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow)
{
// Transfrom geoposition to Point on canvas
Projection projection = mapView.getProjection();
Point point = new Point();
projection.toPixels(geopoint, point);
// background
Paint background = new Paint();
background.setColor(Color.WHITE);
RectF rect = new RectF();
rect.set(point.x + 2 * CIRCLERADIUS, point.y - 4 * CIRCLERADIUS,
point.x + 90, point.y + 12);
// text "My Location"
Paint text = new Paint();
text.setAntiAlias(true);
text.setColor(Color.BLUE);
text.setTextSize(12);
text.setTypeface(Typeface.MONOSPACE);
// the circle to mark the spot
Paint circle = new Paint();
circle.setColor(Color.BLUE);
circle.setAntiAlias(true);
canvas.drawRoundRect(rect, 2, 2, background);
canvas.drawCircle(point.x, point.y, CIRCLERADIUS, circle);
canvas.drawText("My Location", point.x + 3 * CIRCLERADIUS, point.y + 3
* CIRCLERADIUS, text);
}
}
It's most definitely a projection error of sorts, since all my geo fix'd coords end up on the Equator, so there are some 0.0 values getting thrown around.
I can provide other details if needed, I'm running the code on the emulator, Maps API Level 8 (Android 2.2) and I get tiles and the CustomOverlay (circle + text) gets displayed, only at a really false position (coords such as 54.foo and 8.bar are way off).
The codebase could be a bit older, then perhaps a projection such as toPixels isn't required anymore ? No idea.
Thanks in advance !
Solved, turns out the "geo fix" command sent via telnet wants a (Lng, Lat) pair, not a (Lat, Lng) pair. Inconsistency at its best ! Thanks for the input.
If you only want to show current location and keep it updating with a small blinking circule on the screen like Google Maps for Android does, then Android has a default implementation of this feature.
MyLocationOverlay myLocationOverlay = new MyLocationOverlay(context, mapView);
myLocationOverlay.enableMyLocation();
mapView.getOverlays().add(myLocationOverlay);
That's it Android will handle everything.
I want to do the following and am kind of stuck on these for a few days:
I was trying to draw polylines (I have encoded polylines, but have managed to decode those) that move when I move the map.
The only solution that I found was for Geopoints to be transformed into screen coordinates... which won't move if I move the map.
I used HelloItemizedOverlay to add about 150 markers and it gets very very slow.
Any idea what to do? I was thinking about threads (handler).
I was looking for some sort of a timer function that executes a given function periodically, say, every 1 minute or so.
I was also looking for ways to clear the Google map from all the markers/lines, etc.
Answers given below :
1) Here's a solution that I used :
/** Called when the activity is first created. */
private List<Overlay> mapOverlays;
private Projection projection;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
linearLayout = (LinearLayout) findViewById(R.id.zoomview);
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
mapOverlays = mapView.getOverlays();
projection = mapView.getProjection();
mapOverlays.add(new MyOverlay());
}
#Override
protected boolean isRouteDisplayed() {
return false;
}
class MyOverlay extends Overlay{
public MyOverlay(){
}
public void draw(Canvas canvas, MapView mapv, boolean shadow){
super.draw(canvas, mapv, shadow);
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(2);
GeoPoint gP1 = new GeoPoint(19240000,-99120000);
GeoPoint gP2 = new GeoPoint(37423157, -122085008);
Point p1 = new Point();
Point p2 = new Point();
Path path = new Path();
Projection projection.toPixels(gP1, p1);
projection.toPixels(gP2, p2);
path.moveTo(p2.x, p2.y);
path.lineTo(p1.x,p1.y);
canvas.drawPath(path, mPaint);
}
courtesy: Drawing a line/path on Google Maps
2) Here's what worked for me :
createMarkers()
{
for(elem:bigList)
{
GeoPoint geoPoint = new GeoPoint((int)(elem.getLat()*1000000), (int) (elem.getLon()*1000000));
OverlayItem overlayItem = new OverlayItem(geoPoint, elem.getName(), elem.getData());
itemizedOverlay.addOverlay(overlayItem);
}
itemizedOverlay.populateNow();
mapOverlays.add(itemizedOverlay); //outside of for loop
}
and in MyOverlay:
public void addOverlay(OverlayItem overlay)
{
m_overlays.add(overlay);
}
public void populateNow()
{
populate();
}
courtesy: stackoverflow.com unknown link
3) The best way is to use a timer class. A very detailed description of the timer class and how to use it is given at this link :
http://life.csu.edu.au/java-tut/essential/threads/timer.html
4) I used this code :
if(!mapOverlays.isEmpty())
{
mapOverlays.clear();
mapView.invalidate();
}
Hope these answers help atleast one other person. Thanks.
I have the same problem. We are developing an iphone app and an android app at the same time. I have 2500 + map overlays. No problem on iphone; a huge performance hit on android when calling populate() after adding all overlays. (Of course, my first try was to call populate() every time after adding an overlay; a typical mistake due to google's tutorial. Now I am calling populate() just once, after all 2500+ overlays have been added to the ItemizedOverlay.)
So the single populate() call takes over 40 seconds to complete on an htc hero device. I had to put in a busy indicator; no progress bar is possible because we cannot get any information about the progress of populate().
I tried another solution: not use ItemizedOverlay but add overlays by hand, subclassing Overlay. Result: indeed it is much faster to add all those overlays to the map; however, the map becomes unusable due to constant calling of the draw() method on each overlay. In my draw method, I tried to optimize as much as possible; I do not create a bitmap every time. My draw() method looks like this:
public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) {
// our marker bitmap already includes shadow.
// centerPoint is the geopoint where we need to put the marker.
if (!shadow) {
Point point = new Point();
mapView.getProjection().toPixels(centerPoint, point);
canvas.drawBitmap(markerBitmap, point.x, point.y, null);
}
}
Here markerBitmap is precomputed. I don't know what else I could optimize. Is there some kind of populate() call required if we are not using ItemizedOverlay??? I could not find any good answers for that.
Right now I resort to caching the ItemizedOverlay once it has been created in a background thread. This way at least the user does not have to wait every time.
For #2, I don't think you solved anything there. Your hard-to-read code is showing how to put markers on overlay and then, how to add that overlay to the map. That's exactly how I do it. I have map with around 300 hotels and it takes around 5 seconds for Android on my Nexus One to create markers. The whole thing is running inside thread and I guess I will have to do some sort of progress bar to let user know what's going on.
I am working on app that already exists on iPhone and it seems iPhone doesn't have any issues to almost instantaneously draw these 300+ markers. I'll have hard time to explain existence of progress bar to my bosses.
If anybody have idea how to optimize this process... I will be grateful.
Here is my code:
...
for (int m = 0; m < ArrList.size(); m++) {
tName = ArrList.get(m).get("name").toString();
tId = ArrList.get(m).get("id").toString();
tLat = ArrList.get(m).get("lat").toString();;
tLng = ArrList.get(m).get("lng").toString();;
try {
lat = Double.parseDouble(tLat);
lng = Double.parseDouble(tLng);
p1 = new GeoPoint(
(int) (lat * 1E6),
(int) (lng * 1E6));
OverlayItem overlayitem = new OverlayItem(p1, tName, tId);
itemizedoverlay.addOverlay(overlayitem);
} catch (NumberFormatException e) {
Log.d(TAG, "NumberFormatException" + e);
}
}
I know I could save some time by avoiding this String > Double conversion, but I don't feel that would give me significant saving.. or it would?
For your 4th question.... simply use the mapOverlays.clear(); method and all the previous markers will be vanished.
code:
if(!mapOverlays.isEmpty()) {
mapOverlays.clear();
mapView.invalidate();
}
Multiple number of drawable objects can be added to a single Overlay which can then be added to the map. Hence, drawing x number of overlay's for x number of objects wouldnt be necessary unless the objects are of different types. Code snippet..
..
Here, CustomPinPoint is my class which extends ItemizedOverlay<OverlayItem>
CustomPinPoint customPinPoint = new CustomPinPoint(drawable, Main.this);
OverlayItem tempOverLayItem = new OverlayItem(
touchedPoint, "PinPoint", "PintPoint 2"); //Point One
customPinPoint.insertPinPoint(tempOverLayItem);
tempOverLayItem = new OverlayItem(new GeoPoint(
(int)(-27.34498 * 1E6), (int)(153.00724 * 1E6)), "PinPoint",
"PintPoint 2"); //Point Two
customPinPoint.insertPinPoint(tempOverLayItem);
overlayList.add(customPinPoint); //Overlay added only once