Issue
This in a bit complex issue so read carefully.
I have tried to realize a map that
-shows my current position,
-when I click on a point in the map, the app should place a custom geoPoint getting latitude and longitude to pass these to an activity to create a new Pub object
-the map on start must show the positions of Pubs saved before
Following this tutorial I have created these class
Class MyMap:
public class MyMap extends MapActivity implements LocationListener {
private MapView mapView;
private LocationManager locManager;
private MapLocationOverlay itemizedOverlay;
GeoPoint point ;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Inflate our UI from its XML layout description.
setContentView(R.layout.mymap);
mapView = (MapView) findViewById(R.id.mapView);
// invalidate the map in order to show changes
mapView.invalidate();
MapController controller = mapView.getController();
// Use the location manager through GPS
locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, this);
//get the current location (last known location) from the location manager
Location location = locManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//if location found display as a toast the current latitude and longitude
if (location != null) {
point = new GeoPoint((int)(location.getLatitude()*1E6),(int)(location.getLongitude() *1E6));
Toast.makeText(
this,
"Current location:\nLatitude: " + location.getLatitude()
+ "\n" + "Longitude: " + location.getLongitude(),
Toast.LENGTH_LONG).show();
controller.animateTo(point);
controller.setZoom(13);
} else {
Toast.makeText(this, "Cannot fetch current location!",
Toast.LENGTH_LONG).show();
}
// fetch the drawable - the pin that will be displayed on the map
Drawable drawable = this.getResources().getDrawable(R.drawable.pin_custom);
// create and add an OverlayItem to the MyItemizedOverlay list
OverlayItem overlayItem = new OverlayItem(point, "", "");
itemizedOverlay = new MapLocationOverlay(drawable,this);
itemizedOverlay.addOverlay(overlayItem);
// add the overlays to the map
mapView.getOverlays().add(itemizedOverlay);
mapView.invalidate();
GestureDetector gd=new GestureDetector(this, new MyGestureDetector ());
itemizedOverlay.setGestureDetector(gd);
//when the current location is found – stop listening for updates (preserves battery)
locManager.removeUpdates(this);
}
protected boolean isRouteDisplayed() {
return false;
}
/* When the activity starts up, request updates */
protected void onResume() {
super.onResume();
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, this);
}
protected void onPause() {
super.onPause();
locManager.removeUpdates(this); //activity pauses => stop listening for updates
}
public void onLocationChanged(Location location) {
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public class MyGestureDetector extends SimpleOnGestureListener {
public boolean onSingleTapConfirmed(MotionEvent event) {
// fetch the correspondent point from the map
GeoPoint p = mapView.getProjection().fromPixels((int) event.getX(),(int) event.getY());
// create an overlay item and clear all others
OverlayItem o = new OverlayItem(p, null, null);
itemizedOverlay.clear();
itemizedOverlay.addOverlay(o);
// add the overlay item
mapView.getOverlays().clear();
mapView.getOverlays().add(itemizedOverlay);
mapView.invalidate();
Geocoder geoCoder = new Geocoder(getBaseContext(),
Locale.getDefault());
// get the address based on the coordinates
try {
List<Address> addresses = geoCoder.getFromLocation(p.getLatitudeE6() / 1E6, p.getLongitudeE6() / 1E6, 1);
String addressString = "";
if (addresses.size() > 0) {
for (int i = 0; i < addresses.get(0)
.getMaxAddressLineIndex(); i++)
addressString += addresses.get(0).getAddressLine(i)
+ " - ";
}
Toast.makeText(getBaseContext(), addressString,
Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return super.onFling(e1, e2, velocityX, velocityY);
}
public boolean onDown(MotionEvent e) {
return false;
}
}
}
And class MapLocationOverlay:
public class MapLocationOverlay extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
private GestureDetector gestureDetector;
private List<Pub> pubList;
private Context context;
public MapLocationOverlay(Context context, List<Pub> pubList, Drawable marker) {
super(boundCenterBottom(marker));
try{
this.context = context;
this.pubList = pubList;
if (pubList == null) {
pubList = new ArrayList<Pub>();
}
populate();
}
catch(RuntimeException e){
}
}
public MapLocationOverlay(Drawable defaultMarker, Context ctx) {
super(boundCenterBottom(defaultMarker));
}
@Override
protected OverlayItem createItem(int i) {
try{
Pub c=pubList.get(i);
GeoPoint point =
new GeoPoint((int) (c.getLatitude() * 1e6), (int) (c.getLongitude() * 1e6));
return new OverlayItem(point, c.getName(), null);
}
catch(RuntimeException e){
}
return mOverlays.get(i);
}
public void addOverlay(OverlayItem overlay) {
mOverlays.add(overlay);
populate();
}
public void clear() {
mOverlays.clear();
populate();
}
@Override
public boolean onTap(final int index) {
Pub c=pubList.get(index);
final String name=c.getName();
final String description=c.getDescription();
final String street=c.getStreet();
// BrewLocation brewLocation = brewLocations.get(index);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Visualizzare la nota "+name+"?")
.setPositiveButton("Si", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent pubDetails = new Intent(context, InfoPub.class);
pubDetails.putExtra("name", name);
pubDetails.putExtra("description", description);
pubDetails.putExtra("street", street);
context.startActivity(pubDetails);
}
}).setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
return true; // we'll handle the event here (true) not pass to another overlay (false)
}
/**
* Override this method to handle a "tap" on a balloon. By default, does nothing
* and returns false.
*
* @param index - The index of the item whose balloon is tapped.
* @return true if you handled the tap, otherwise false.
*/
protected boolean onBalloonTap(int index) {
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event, MapView mapView) {
// when the user lifts its finger
if (gestureDetector.onTouchEvent(event)) {
return true;
}
return false;
}
public GestureDetector getGestureDetector() {
return gestureDetector;
}
public void setGestureDetector(GestureDetector gestureDetector) {
this.gestureDetector = gestureDetector;
}
@Override
public int size() {
//return pubList.size();
return mOverlays.size();
}
}
Is not totally complete but should run, according the tutorial followed, unfortunately when I try to launch the activity the app crash with a fatal error.
This is the error stack:
10-13 17:25:56.109: E/AndroidRuntime(28215): FATAL EXCEPTION: main
10-13 17:25:56.109: E/AndroidRuntime(28215): java.lang.RuntimeException: Unable to start activity ComponentInfo{it.myapp.mymapapp/it.myapp.mymapapp.MyMap}: java.lang.NullPointerException
10-13 17:25:56.109: E/AndroidRuntime(28215): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1651)
10-13 17:25:56.109: E/AndroidRuntime(28215): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
10-13 17:25:56.109: E/AndroidRuntime(28215): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
10-13 17:25:56.109: E/AndroidRuntime(28215): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
10-13 17:25:56.109: E/AndroidRuntime(28215): at android.os.Handler.dispatchMessage(Handler.java:99)
10-13 17:25:56.109: E/AndroidRuntime(28215): at android.os.Looper.loop(Looper.java:130)
10-13 17:25:56.109: E/AndroidRuntime(28215): at android.app.ActivityThread.main(ActivityThread.java:3687)
10-13 17:25:56.109: E/AndroidRuntime(28215): at java.lang.reflect.Method.invokeNative(Native Method)
10-13 17:25:56.109: E/AndroidRuntime(28215): at java.lang.reflect.Method.invoke(Method.java:507)
10-13 17:25:56.109: E/AndroidRuntime(28215): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
10-13 17:25:56.109: E/AndroidRuntime(28215): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
10-13 17:25:56.109: E/AndroidRuntime(28215): at dalvik.system.NativeStart.main(Native Method)
10-13 17:25:56.109: E/AndroidRuntime(28215): Caused by: java.lang.NullPointerException
10-13 17:25:56.109: E/AndroidRuntime(28215): at com.google.android.maps.ItemizedOverlay.populate(ItemizedOverlay.java:312)
10-13 17:25:56.109: E/AndroidRuntime(28215): at it.myapp.mymapapp.utility.MapLocationOverlay.addOverlay(MapLocationOverlay.java:72)
10-13 17:25:56.109: E/AndroidRuntime(28215): at it.myapp.mymapapp.MyMap.onCreate(MyMap.java:89)
10-13 17:25:56.109: E/AndroidRuntime(28215): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
10-13 17:25:56.109: E/AndroidRuntime(28215): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
10-13 17:25:56.109: E/AndroidRuntime(28215): ... 11 more
How Could I fix this? What's missing?
Solution
You are not initializing point
in onCreate()
, except if you get a valid lastKnownLocation()
.
This non initialized point
is added to an OverlayItem, that is added to the ItemizedOverlay.
When Mapview try to get the Geopoint to draw Marker, it gets a null
and bummmm!!
Just replace:
GeoPoint point;
by:
GeoPoint point = new Geopoint(0,0);
and it will not crash anymore.
Answered By - Luis
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.