尝试启动自定义MapActivity时出现致命错误

时间:2012-10-13 17:52:00

标签: android android-mapview android-maps geopoints

这有点复杂,所以仔细阅读。

我试图实现一张

的地图

- 显示我目前的职位,

- 当我点击地图中的某个点时,应用应该放置一个自定义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

我该如何解决这个问题? 有什么遗漏?

2 个答案:

答案 0 :(得分:1)

您没有在point中初始化onCreate(),除非您获得有效的lastKnownLocation()

这个未初始化的point被添加到OverlayItem中,并被添加到ItemizedOverlay中。

当Mapview尝试让Geopoint绘制标记时,它会得到null和bummmm !!

只需替换:

GeoPoint point;

由:

GeoPoint point = new Geopoint(0,0); 

它不会再崩溃了。

答案 1 :(得分:0)

您的createItem()实施很奇怪:

  1. 你抓住了RuntimeException并且没有做任何事情。如果不出意外,您应该记录异常,特别是只要您的代码出现问题。

  2. 您的size()方法基于mOverlays,但您未在mOverlays中使用createItem()(除非发生错误处理的RuntimeException) 。要么始终使用mOverlays,要么完全摆脱它。

  3. 除此之外,ItemizedOverlay期望不是null的内容确实是null。一种可能性是“片段”(OverlayItem构造函数的第三个参数),您将其设置为null。另一种可能性是c.getName()正在返回null,可能ItemizedOverlay需要该名称为非null

    如果没有别的,请回到该博客帖子中的原始代码,使其正常工作,然后慢慢地修改它以获得所需的功能,并随时进行测试。