这有点复杂,所以仔细阅读。
我试图实现一张
的地图- 显示我目前的职位,
- 当我点击地图中的某个点时,应用应该放置一个自定义geoPoint获取纬度和经度,以将这些传递给活动以创建新的Pub对象
- 开始时的地图必须显示
之前保存的酒吧的位置关注this tutorial我创建了这些类
类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;
}
}
}
上课 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();
}
}
根据下面的教程,不完整但应该运行,不幸的是,当我尝试启动活动时,应用程序崩溃并发生致命错误。
这是错误堆栈:
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
我该如何解决这个问题? 有什么遗漏?
答案 0 :(得分:1)
您没有在point
中初始化onCreate()
,除非您获得有效的lastKnownLocation()
。
这个未初始化的point
被添加到OverlayItem中,并被添加到ItemizedOverlay中。
当Mapview尝试让Geopoint绘制标记时,它会得到null
和bummmm !!
只需替换:
GeoPoint point;
由:
GeoPoint point = new Geopoint(0,0);
它不会再崩溃了。
答案 1 :(得分:0)
您的createItem()
实施很奇怪:
你抓住了RuntimeException
并且没有做任何事情。如果不出意外,您应该记录异常,特别是只要您的代码出现问题。
您的size()
方法基于mOverlays
,但您未在mOverlays
中使用createItem()
(除非发生错误处理的RuntimeException
) 。要么始终使用mOverlays
,要么完全摆脱它。
除此之外,ItemizedOverlay
期望不是null
的内容确实是null
。一种可能性是“片段”(OverlayItem
构造函数的第三个参数),您将其设置为null
。另一种可能性是c.getName()
正在返回null
,可能ItemizedOverlay
需要该名称为非null
。
如果没有别的,请回到该博客帖子中的原始代码,使其正常工作,然后慢慢地修改它以获得所需的功能,并随时进行测试。