3

我正在尝试使用 MapView 类进行 GoogleMap 显示,但没有运气,因为大多数代码示例都使用我不想要的 MapFragment。

我正在使用 Google Maps Android API v2。

起初,只是为了在 Google 的示例中进行测试,我设法获得了要显示的典型法线贴图。

public class POnlineMapView extends Activity {

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.online_map_activity);
    }
}

上面的代码完美运行,表明一切都已正确设置。

我现在正在尝试使用 MapView 类来操作显示设置,例如中心点,但似乎每次尝试获取 GoogleMap 对象时我都在获取一个空对象。为什么会这样?

public class POnlineMapView extends Activity {

    private MapView myMapView;
    private GoogleMap map;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        myMapView = new MapView(getApplicationContext());
        Bundle b = getIntent().getExtras();
        double longitude = b.getDouble("longitude");
        double latitude = b.getDouble("latitude");

        setContentView(R.layout.online_map_activity);
        map = myMapView.getMap();

        CameraUpdate center= CameraUpdateFactory.newLatLng(new LatLng(latitude,longitude));
        CameraUpdate zoom=CameraUpdateFactory.zoomTo(17);

        map.moveCamera(center); //this gives a NullPointerException, probably due to the myMapView.getMap() method?
        map.animateCamera(zoom);    
    }
}
4

6 回答 6

3

这似乎是一个老问题,但我在尝试使用 MapView 时遇到了同样的问题。

假设您已正确导入 Google Play Services 库,您必须检查您是否可以访问 Google 服务,您可以在 onCreate 方法中执行此操作,并且您必须初始化 Google Maps Android AP。您可以通过将以下代码添加到您的 onCreate 方法来做到这一点

try {
        MapsInitializer.initialize(this);
    } catch (GooglePlayServicesNotAvailableException e) {
        Log.e("Address Map", "Could not initialize google play", e);
    }

switch (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) )
{
  case ConnectionResult.SUCCESS:
      Toast.makeText(getApplicationContext(), "SUCCESS", Toast.LENGTH_SHORT).show();
      break;
  case ConnectionResult.SERVICE_MISSING: 
      Toast.makeText(getApplicationContext(), "SERVICE MISSING", Toast.LENGTH_SHORT).show();
      break;
  case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED: 
      Toast.makeText(getApplicationContext(), "UPDATE REQUIRED", Toast.LENGTH_SHORT).show();
      break;
  default: Toast.makeText(getApplicationContext(), GooglePlayServicesUtil.isGooglePlayServicesAvailable(this), Toast.LENGTH_SHORT).show();
}

如果您获得成功,那么到目前为止一切正常。您还必须实现 Activity lyfecycle 的方法,并在以下每个方法中调用地图视图的相应方法:

@Override
protected void onResume() {
    myMapView.onResume();
    super.onResume();

}

@Override
protected void onPause() {
    myMapView.onResume();
    super.onPause();

}

@Override
protected void onDestroy() {
    myMapView.onDestroy();
    super.onDestroy();
   //((MapView)findViewById(R.id.mapView)).onDestroy();
}

@Override
public void onLowMemory() {
    super.onLowMemory();
    myMapView.onLowMemory();
}

最后,您必须检查您是否已将 Google Maps API 密钥添加到您的清单文件中:

<meta-data
        android:name="com.google.android.maps.v2.API_KEY"
        android:value="YOUR KEY"/>

您可以在此处找到获取密钥的说明:https ://developers.google.com/maps/documentation/android/start#installing_the_google_maps_android_v2_api

编辑:忘了提,您还必须在清单文件上设置您的应用程序权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

这必须在应用程序块内设置...

于 2013-10-17T06:01:44.523 回答
3

检查是否已安装(和更新)Google Play 服务

Google Maps Android API v2 throws GooglePlayServicesNotAvailableException, out of date, SupportMapFragment.getMap() 返回 null

另请阅读https://developers.google.com/maps/documentation/android/map(验证地图可用性部分)

于 2013-01-25T09:43:52.113 回答
3

Thanks, you finally gave me a clue to initialize the Map programatically, how stupid I oversaw it :)

Well, sometimes there is no option to use MapFragment (or SupportMapFragment alike), i.e. when you want to use the map from a fragment! This is actually a very common case when working with tabs (ActionBar) where the pattern is to use fragments. So you've got your own fragment per tab and in that fragment for a map you want to inflate your layout which contains a fragment for the MapFragment, et voila - good luck!

Now, according to the MapView specs it is no way said that using of the MapView is discouraged or deprecated, so why should I not use it? I did not want hacks in maintaining nested fragments without having support from SDK ( even the recent support lib v13 seems to have bugs and nested fragments from layout are not supported ), so using MapView turned for me into KISS.

Below is my CustomMapFragment I use with layout inflation (allowing complex layout) and embedded map, you're welcome to use it. You may also want to extend the Fragment from support-lib rather than SDK.

The onCreateView() method inflates the layout (just provide you're own) and expects the layout to have viewgroup (relativelayout,linearlayout,etc) with id "mapViewHolder" where the mapView will be attached to upon layout creation. The activity has to implement CustomMapFragment.Handler interface, otherwise ClassCastException will be thrown.

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import R;

public class AppMapFragment extends Fragment {
  /*
   * to interact with activity
   */
  public static interface Handler {
    void onMapResume(GoogleMap map);
  }

  private Handler handler;
  private MapView mapView;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    try {
      // initialize explicitely, since we're working with MapView (not MapFragment)
      MapsInitializer.initialize(getActivity());
      this.mapView = new MapView(getActivity());
      this.mapView.onCreate(savedInstanceState);
    } catch (GooglePlayServicesNotAvailableException e) {
      Toast.makeText(getActivity(), "Please install Google Play Store and retry again!", Toast.LENGTH_LONG).show();
      getActivity().finish();
    }
  }

  @Override
  public void onResume() {
    super.onResume();
    this.mapView.onResume();
    this.handler.onMapResume(this.mapView.getMap());
  }

  @Override
  public void onPause() {
    super.onPause();
    this.mapView.onPause();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    this.mapView.onDestroy();
  }

  @Override
  public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    this.mapView.onSaveInstanceState(outState);
  }

  @Override
  public void onLowMemory() {
    super.onLowMemory();
    this.mapView.onLowMemory();
  }

  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
      this.handler = (Handler) activity;
    } catch (ClassCastException e) {
      throw new ClassCastException("Your activity has to implement the interface " + this.handler.getClass().getName());
    }
  }

  public AppMapFragment() {
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_results_map, container, false);

    ((ViewGroup) rootView.findViewById(R.id.mapViewHolder)).addView(this.mapView);

    return rootView;
  }
}
于 2013-12-10T21:09:49.337 回答
1

MapFragment 和 MapView 之间的一个区别是您必须手动管理 MapView 的生命周期,而 MapFragment 会自行处理它。

您必须从父 Activity/Fragment 的相应方法中调用以下方法。

onCreate(Bundle)
onResume()
onPause()
onDestroy()
onSaveInstanceState()
onLowMemory()

我在 Google Play 服务示例中使用 RawMapViewDemoActivity 验证了这一点,可以将其安装在 Android SDK 管理器的 Extras 部分。

示例首先显示地图,一旦我注释掉mMapView.onXXX() 的6 行,它显示一个空白页。

也许生命周期是我们随处可见的大多数示例使用 MapFragment 的原因。

于 2014-07-06T15:12:29.633 回答
0

我对地图视图也没有运气。
我确实对 MapFragment 很幸运。

尝试这个:

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;

public class TestActivity extends FragmentActivity {

  SupportMapFragment mapFragment;
  GoogleMap map;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (mapFragment == null) {
      mapFragment = new SupportMapFragment();
      getSupportFragmentManager().beginTransaction()
          .add(android.R.id.content, mapFragment).commit();
    }
  }

  @Override
  protected void onResume() {
    super.onResume();
    setupMap();
  }

  private void setupMap() {
    if (map != null)
      return;
    map = mapFragment.getMap();
    if (map == null)
      return;

    doZoom();
  }

  private void doZoom() {
    if (map != null) {
      map.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(45.424900,
          -75.694968), 17));
    }
  }
}
于 2013-01-31T21:12:48.000 回答
0

试试这种方式:

  private MapView myMapView;   
  private GoogleMap map;  
      myMapView = (MapView) findViewById(R.id.map);     
      if (map == null) {     
                map = ((MapView) findViewById(R.id.map)).getMap();     
       }
于 2013-01-25T08:41:02.263 回答