One part of the application I am making requires google map. I want the user to be able to type into edittext some search string and then press a search button and the map will animate to the first result.
When I press the button the application searches and takes the first result and puts it into a geopoint, so that part of the program is working. But when I try to animate to that point the application crashes.
Here is the onCreate function where I successfully navigate to the location "Dalvík, Iceland".
public class LocationPicker extends MapActivity {
static GeoPoint point;
static MapController mc;
static MapView mapView;
private EditText location;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location_picker);
MapView mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
location = (EditText)findViewById(R.id.locationString);
mc = mapView.getController();
String tmp = "Dalvík, Iceland";
try {
point = searchLocation(tmp);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mc.animateTo(point);
mc.setZoom(14);
MapOverlay mapOverlay = new MapOverlay();
List<Overlay> listOfOverlays = mapView.getOverlays();
listOfOverlays.clear();
listOfOverlays.add(mapOverlay);
mapView.invalidate();
}
And my code for the button click is, and to be clear the System.out.println(point) prints valid point. But still when I click the button my application crashes.
public void search(View v) throws IOException{
GeoPoint tmpPoint = searchLocation(location.getText().toString());
System.out.println(tmpPoint);
if( tmpPoint != null){
mc.animateTo(tmpPoint);
mapView.invalidate();
}
}
And the searchLocation functions is as follows:
public GeoPoint searchLocation (String searchString) throws IOException{
Geocoder geo = new Geocoder(this);
List<Address> addr;
addr = geo.getFromLocationName(searchString, 10);
if(!addr.isEmpty()){
Address loc = addr.get(0);
GeoPoint point = new GeoPoint((int) (loc.getLatitude() * 1E6),
(int) (loc.getLongitude() * 1E6));
return point;
}
else {
return null;
}
}
So to summerize I am clearly doing something wrong in the onclick "search" function.
Any ideas what is wrong?
You are not checking the right variable for null value:
if( point != null){
mc.animateTo(tmpPoint);
mapView.invalidate();
}
should be
if( tmpPoint!= null){
mc.animateTo(tmpPoint);
mapView.invalidate();
}
Additionnally, you want to make the call to the geoCoder.getFromLocationName method outside the UI thread as this can be time consumming. Use an AsyncTask for that for instance.
Finally, even if you get a list of addresses, they are not guaranted to have latitude and longitude. Use the hasLatitude and hasLongitude functions to pick the first address of the result list with coordinates.
I found the answer.
The problem causing this was this line
mapView.invalidate();
Related
I am trying to buid a simple app that when user enter his desired location its map appear.But i am getting an error Cannot instantiate the type GeoPoint i have also installed Google Play Services.
here is the code :
public class MainActivity extends MapActivity {
EditText location;
Geocoder geoCoder;
GeoPoint p;
MapController controller;
MapView mapView;
Button btnSearch;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
location=(EditText)findViewById(R.id.txtAddress);
mapView = (MapView) findViewById(R.id.mapView);
btnSearch.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
List<Address> addresses;
try {
addresses = geoCoder.getFromLocationName(location.getText().toString(),1);
if(addresses.size() > 0)
{
p = new GeoPoint( (int) (addresses.get(0).getLatitude() * 1E6),
(int) (addresses.get(0).getLongitude() * 1E6));
controller.animateTo(p);
controller.setZoom(12);
MapOverlay mapOverlay = new MapOverlay();
List<Overlay> listOfOverlays = mapView.getOverlays();
listOfOverlays.clear();
listOfOverlays.add(mapOverlay);
mapView.invalidate();
location.setText("");
}
else
{
AlertDialog.Builder adb = new AlertDialog.Builder(MainActivity.this);
adb.setTitle("Google Map");
adb.setMessage("Please Provide the Proper Place");
adb.setPositiveButton("Close",null);
adb.show();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
Is there a particular reason you need to use v1 of the Google maps api, instead of the current v2? If not, try using LatLng to store the location, and map.moveCamera(LatLng, float zoom) to go to the desired location as shown here.
when you go to Google maps in the browser you can type a country name and the map focuses on that country. Is it possible to get this on a MapView? I'd like my MapView to initially focus on user's country if a location is not available.
EDIT: here's what I have so far:
private MapView mvClear;
private MyLocationOverlay compass;
private MapController controller;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clear_map);
mvClear = (MapView) findViewById(R.id.mvClear);
mvClear.setBuiltInZoomControls(true);
TouchOverlay touchOverlay = new TouchOverlay();
List<Overlay> overlays = mvClear.getOverlays();
overlays.add(touchOverlay);
compass = new MyLocationOverlay(this, mvClear);
overlays.add(compass);
controller = mvClear.getController();
controller.setZoom(8);
Geocoder coder = new Geocoder(this);
try {
List<Address> address = coder.getFromLocationName(Locale.getDefault().getCountry(), 1);
int lat = (int) address.get(0).getLatitude();
int lon = (int) address.get(0).getLongitude();
GeoPoint point = new GeoPoint(lat, lon);
controller.setCenter(point);
} catch (IOException e) {
e.printStackTrace();
}
}
No focus.
Best solution I found was to save the default center point as String resource so it can be "translated" if the app is localized. That's it for now..
Google map, it allows us to pin-point any location we want. After pin-pointing, there will be this "Bubble" pop up box at the top of the push-pin. May i know how to do the pop up window box? Any codes to show? I am using alert dialog box now, but i want it to be "Bubble" pop up window instead.
List<Overlay> mapOverlays = mapView.getOverlays();
MapOverlay mapOverlay = new MapOverlay();
mapOverlays.add(mapOverlay);
// obtain gps location
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationListener();
lm.requestLocationUpdates(
// LocationManager.GPS_PROVIDER,
LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
k = new GeoPoint((int) (loc.getLatitude() * 1E6),
(int) (loc.getLongitude() * 1E6));
mc.animateTo(k);
mc.setZoom(18);
// Add a location marker
MapOverlay mapOverlay = new MapOverlay();
List<Overlay> listofOverlays = mapView.getOverlays();
listofOverlays.clear();
listofOverlays.add(mapOverlay);
// invalidate() method forces the MapView to be redrawn
mapView.invalidate();
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
#Override
protected boolean isRouteDisplayed() {
return false;
}
class MapOverlay extends com.google.android.maps.Overlay {
#Override
public boolean onTap(final GeoPoint p, MapView mapView) {
// TODO Auto-generated method stub
k = p;
mc = mapView.getController();
mc.animateTo(p);
mapView.invalidate();
Geocoder geoCoder = new Geocoder(getBaseContext(),
Locale.getDefault());
try {
List<Address> addresses = geoCoder.getFromLocation(
p.getLatitudeE6() / 1E6, p.getLongitudeE6() / 1E6, 1);
String add = "";
if (addresses.size() > 0) {
for (int i = 0; i < addresses.get(0)
.getMaxAddressLineIndex(); i++)
add += addresses.get(0).getAddressLine(i) + "\n";
txtAddress.setText("Address: " + add);
}
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
long when) {
super.draw(canvas, mapView, shadow);
if (k != null) {
// ---translate the GeoPoint to screen pixels---
Point screenPts = new Point();
mapView.getProjection().toPixels(k, screenPts);
// ---add the marker---
Bitmap bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.passenger);
canvas.drawBitmap(bmp, screenPts.x, screenPts.y - 50, null);
}
return true;
}
}
}
I'm currently working on a mapping application where I also needed to display 'Bubble' popups and the following blog posts helped me quite a bit.
This first post shows how to use a 9-patch image embedded in a view to produce a popup. The code is ok but does leave a number of questions unanswered, some commenters have requested some additional source code for clarification.
This post from the Android Developers blog explains what a 9 patch image is an how to create one.
Using these two posts I was able to pull some code together which works well so hopefully you will be able to manipulate it to fit your needs too.
Sounds like you are looking for the InfoWindow. By the way, in newer versions of the API, they do not have rounded corners (they look more like boxes and less like bubbles). You can restore the old ones by requesting a previous version of the API in the javascript URL that loads the maps API.
Google doesn't provide an API to do this, take a look at this. Victor's answer gives a link to open source code which fits the bill.
I've been developing an app that reads a .csv file, takes out approximately 16 latitude/longitude points, and plots them on a Google Map.
However, it seems that the points don't like to plot until I touch the screen after about a minute (I have no listeners established) [this is a separate problem that maybe someone can answer as well].
The task of getting the latitude/longitude points and plotting them is put into an AsyncTask doInBackground method. Refreshing the map's drawable state is done in the AsyncTask's onPostExecute method.
I figured that I would eliminate lag since I have the AsyncTask method working for me. When the program starts, it shows a blank map, I wait about 15 seconds and, if I touch the map, the points will plug in. However, the map is unbearably laggy at this point! It takes the app at least 5 seconds to respond to my interaction (i.e. zoom, scroll), and even then it does the action really slow...
Does anything think they know the cause of this?
Here's most of my code:
package net.learn2develop.GoogleMaps;
-- imports here
public class MapsActivity extends MapActivity
{
MapView mapView;
MapController mc;
//GeoPoint p;
//GeoPoint p2;
GeoPoint[] p99 = new GeoPoint[16];
public static String[][] bump = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mapView = (MapView) findViewById(R.id.mapView);
LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom);
#SuppressWarnings("deprecation")
View zoomView = mapView.getZoomControls();
mapView.setStreetView(true);
mapView.setSatellite(false);
zoomLayout.addView(zoomView,
new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
mapView.displayZoomControls(true);
mc = mapView.getController();
// Add points from ReadCsv.java
/** try/catch to-> async was cut from here */
new MapPoint().execute(bump);
mapView.invalidate();
}
public String[][] getArray(BufferedReader bufRdr) {
-- my method that I know works
}
#Override
protected boolean isRouteDisplayed() {
return false;
}
class MapOverlay extends com.google.android.maps.Overlay {
#Override
public boolean draw(Canvas canvas, MapView mapView,
boolean shadow, long when)
{
super.draw(canvas, mapView, shadow);
// -- array of points---
for(int i = 0; i < bump.length; i++) {
Point screenPts99 = new Point();
mapView.getProjection().toPixels(p99[i], screenPts99);
Bitmap bmp99 = BitmapFactory.decodeResource(
getResources(), R.drawable.redpin);
canvas.drawBitmap(bmp99, screenPts99.x, screenPts99.y-44, null);
}
return true;
}
}
private class MapPoint extends AsyncTask <String[][], String, String> {
#Override
protected String doInBackground(String[][]... voidThisArray) {
String voidThisString = null;
try {
InputStream is = getAssets().open("Training4.csv");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
bump = getArray(reader);
if(bump == null){
setContentView(R.layout.deleteme);
} else {
for(int i = 0; i < bump.length; i++) {
String coordinates99[] = {bump[i][0], bump[i][1]};
double lat99 = Double.parseDouble(coordinates99[0]);
double lng99 = Double.parseDouble(coordinates99[1]);
p99[i] = new GeoPoint(
(int) (lat99 * 1E6),
(int) (lng99 * 1E6));
MapOverlay mapOverlay99 = new MapOverlay();
List<Overlay> listOfOverlays99 = mapView.getOverlays();
listOfOverlays99.add(mapOverlay99);
mapView.refreshDrawableState();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return voidThisString;
}
#Override
protected void onPostExecute(String voidThisString) {
super.onPostExecute(voidThisString);
mapView.refreshDrawableState();
mapView.invalidate();
}
}
}
in onPostExecute use the mapView.invalidate(); method it'll refresh it and whatever you done in inBackground() that will be refreshing by this method
you add the MapOverlay in for loop so what happen each overlay contain bump.length points.
so it will getting slow add dupplication of point.
first get all the lat/lng and store in p99 array and then add the mapoverlay
implement code
try {
InputStream is = getAssets().open("Training4.csv");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
bump = getArray(reader);
if(bump == null){
setContentView(R.layout.deleteme);
} else {
for(int i = 0; i < bump.length; i++) {
String coordinates99[] = {bump[i][0], bump[i][1]};
double lat99 = Double.parseDouble(coordinates99[0]);
double lng99 = Double.parseDouble(coordinates99[1]);
p99[i] = new GeoPoint(
(int) (lat99 * 1E6),
(int) (lng99 * 1E6));
}
MapOverlay mapOverlay99 = new MapOverlay();
List<Overlay> listOfOverlays99 = mapView.getOverlays();
listOfOverlays99.add(mapOverlay99);
mapView.refreshDrawableState();
}
} catch (IOException e) {
e.printStackTrace();
}
your draw()
public boolean draw(Canvas canvas, MapView mapView,
boolean shadow, long when)
{
super.draw(canvas, mapView, shadow);
// -- array of points---
if(bump!=null){
for(int i = 0; i < bump.length; i++) {
Point screenPts99 = new Point();
mapView.getProjection().toPixels(p99[i], screenPts99);
Bitmap bmp99 = BitmapFactory.decodeResource(
getResources(), R.drawable.redpin);
canvas.drawBitmap(bmp99, screenPts99.x, screenPts99.y-44, null);
}
}
return true;
}
I have a mapview page that displays the current location in the map.
I am using MyLocationOverlay for the purpose. The code for that goes as follows:
myLocationOverlay = new MyLocationOverlay(this, mapView);
myLocationOverlay.enableCompass();
myLocationOverlay.enableMyLocation();
myLocationOverlay.runOnFirstFix(new Runnable() {
public void run() {
geopoint = myLocationOverlay.getMyLocation();
ItemizedOverlay itemizedoverlay = new ItemizedOverlay(drawable);
try{
overlayitem = new OverlayItem(geopoint, "", "");
}
catch(Exception e){
e.printStackTrace();
}
itemizedoverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedoverlay);
mapController.animateTo(geoPoint);
}
});
The above code works and gets the current location through gps and sets a marker at that point.
But the code inside try block is the issue.
I am getting null value inside geopoint.
Actually I have to get that point and do some calculations with distance and all. For that I have to get the correct value inside that geopoint.
Can anyone please tell the solution for this?
I've been working on the same problem for a day now and here's what I've discovered. For some reason this works
LocationManager lm;
GeoPoint gp;
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
Location lastKnownLoc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastKnownLoc != null){
int longTemp = (int)(lastKnownLoc.getLongitude()* 1000000);
int latTemp = (int)(lastKnownLoc.getLatitude() * 1000000);
gp = new GeoPoint(latTemp, longTemp);
}
and this doesn't
gp = myLocOverlay.getMyLocation();
Tracking current location can be done by using MyLocationOverlay class and through LocationManager. Using MyLocationOverlay, the code below works..
MyLocationOverlay myLocationOverlay;
MapView mapView;
MapController mapcontroller;
OverlayItem overlayitem;
List<Overlay> mapoverlays;
GeoPoint geopoint;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.currentlocation);
mapView = (MapView) findViewById(R.id.map);
mapView.setBuiltInZoomControls(true);
mapView.setSatellite(false);
mapView.setStreetView(true);
mapView.setTraffic(true);
mapcontroller = mapView.getController();
mapoverlays = mapView.getOverlays();
drawable = this.getResources().getDrawable(R.drawable.ic_map_red);
mapView.invalidate();
getCurrentLocation();
}
public void getCurrentLocation(){
myLocationOverlay = new MyLocationOverlay(this, mapView);
myLocationOverlay.enableCompass();
myLocationOverlay.enableMyLocation();
myLocationOverlay.runOnFirstFix(new Runnable() {
public void run() {
ItemizedOverlay itemizedoverlay = new ItemizedOverlay(drawable);
try {
latitude = myLocationOverlay.getMyLocation().getLatitudeE6();
longitude = myLocationOverlay.getMyLocation().getLongitudeE6();
geopoint = new GeoPoint((int) (latitude), (int) (longitude));
overlayitem = new OverlayItem(geopoint, "", "");
itemizedoverlay.addOverlay(overlayitem);
mapoverlays.add(itemizedoverlay);
mapcontroller.animateTo(geopoint);
mapcontroller.setZoom(16);
}
catch (Exception e) {}
}
});
}
If you override:
onLocationChanged();
Remember to call:
super.onLocationChanged();
after or before your own code. This appears to ensure that the variable
getMyLocation()
returns is not null.
The friend upstairs made me rise that try override nothing, neither draw nor drawMyLocation.
Just like this:
MyLocationOverlay myLocationOverlay = new SelfLocationOverlay(this, mapView);
myLocationOverlay.enableMyLocation();
myLocationOverlay.disableCompass();
mapView.getOverlays().add(myLocationOverlay);