简体   繁体   English

Google Map Android API v2:GoogleMap为空

[英]Google Map Android API v2 : GoogleMap is null

I'm trying to explore using the MapView class for GoogleMap display, with no luck, as most codes examples are using MapFragment which I do not want. 我正在尝试使用MapView类进行GoogleMap显示,没有运气,因为大多数代码示例都使用了我不想要的MapFragment。

I am using Google Maps Android API v2. 我使用的是Google Maps Android API v2。

At first, just for testing with here from Google's example , I managed to get the typical normal map to display. 首先,仅仅是为了通过Google的示例进行测试,我设法得到了典型的法线贴图。

public class POnlineMapView extends Activity {

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

The code above works perfectly which show that everything has been set up properly. 上面的代码完美地运行,表明一切都已正确设置。

I am now trying to use the MapView class to manipulate the display settings such as the center point, but it seems like I am obtaining a null object everytime I try to obtain the GoogleMap object. 我现在正在尝试使用MapView类来操作显示设置,例如中心点,但似乎我每次尝试获取GoogleMap对象时都会获得一个null对象。 Why is this so? 为什么会这样?

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);    
    }
}

This seems like an old question, but I was having the same problem trying to use MapView. 这似乎是一个老问题,但我在尝试使用MapView时遇到了同样的问题。

Assuming you have properly imported the Google Play Services lib, you have to check if you have access to Google Services, you can do this in your onCreate method, and you have to initialize the Google Maps Android AP. 假设您已正确导入Google Play服务库,则必须检查您是否可以访问Google服务,您可以使用onCreate方法执行此操作,并且必须初始化Google Maps Android AP。 you can do this by adding the following code to your onCreate method 您可以通过将以下代码添加到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();
}

If you get SUCCESS, then everything is working so far. 如果你获得了SUCCESS,那么到目前为止一切正常。 You also have to implement the mothods of the Activity lyfecycle and call the corresponding methond of your map view inside every one of these methods: 您还必须实现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();
}

Finally, you have to check that you have added your Google Maps API key to your Manifest file: 最后,您必须检查是否已将Google Maps API密钥添加到Manifest文件中:

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

you can find instructions to get your key here: https://developers.google.com/maps/documentation/android/start#installing_the_google_maps_android_v2_api 您可以在此处找到获取密钥的说明: https//developers.google.com/maps/documentation/android/start#installing_the_google_maps_android_v2_api

Edit: Forgot to mention, you also have to set your applications permissions on the manifest file 编辑:忘记提及,您还必须在清单文件上设置您的应用程序权限

<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"/>

This has to be set inside the application block ... 这必须在应用程序块中设置...

Thanks, you finally gave me a clue to initialize the Map programatically, how stupid I oversaw it :) 谢谢,你终于给了我一个以编程方式初始化Map的线索,我是多么愚蠢地监督它:)

Well, sometimes there is no option to use MapFragment (or SupportMapFragment alike), ie when you want to use the map from a fragment! 好吧,有时没有选择使用MapFragment(或类似SupportMapFragment),即当你想使用片段中的地图时! This is actually a very common case when working with tabs (ActionBar) where the pattern is to use fragments. 在处理模式使用片段的制表符(ActionBar)时,这实际上是一种非常常见的情况。 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! 所以你在每个标签上都有自己的片段,在那个片段中你想要给你的布局充气,其中包含一个MapFragment的片段,等等 - 祝你好运!

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? 现在,根据MapView规范,没有办法说不鼓励或不赞成使用MapView,那么我为什么不使用它呢? 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. 我不想在没有SDK支持的情况下维护嵌套片段(即使最近的支持lib v13似乎有bug,也不支持布局中的嵌套片段),所以使用MapView转向KISS。

Below is my CustomMapFragment I use with layout inflation (allowing complex layout) and embedded map, you're welcome to use it. 下面是我使用的CustomMapFragment布局膨胀(允许复杂的布局)和嵌入式地图,欢迎您使用它。 You may also want to extend the Fragment from support-lib rather than SDK. 您可能还希望从support-lib而不是SDK扩展Fragment。

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. onCreateView()方法使布局膨胀(只是提供你自己的)并期望布局具有id为“mapViewHolder”的viewgroup(relativelayout,linearlayout等),其中mapView将在创建布局时附加到。 The activity has to implement CustomMapFragment.Handler interface, otherwise ClassCastException will be thrown. 该活动必须实现CustomMapFragment.Handler接口,否则将抛出ClassCastException。

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;
  }
}

One difference between MapFragment and MapView is that you have to manually manage the lifecycle of MapView, while MapFragment takes care of it by itself. MapFragment和MapView之间的一个区别是您必须手动管理MapView的生命周期,而MapFragment会自行处理它。

You must call the following methods from the parent Activity/Fragment's corresponding methods. 您必须从父Activity / Fragment的相应方法调用以下方法。

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

I verified this with RawMapViewDemoActivity in samples of Google Play Services, which can be installed in the Extras section of Android SDK Manager. 我在Google Play服务的示例中使用RawMapViewDemoActivity对此进行了验证,该示例可以安装在Android SDK Manager的Extras部分中。

The sample showed the map at first, and it showed a blank page once I commented out the 6 lines of mMapView.onXXX(). 样本首先显示了地图,一旦我注释掉了6行mMapView.onXXX(),它就会显示一个空白页面。

Maybe the lifecycle is the reason why most examples we see everywhere use MapFragment. 也许生命周期是我们到处看到的大多数示例都使用MapFragment的原因。

Try out this way: 试试这种方式:

  private MapView myMapView; private GoogleMap map; myMapView = (MapView) findViewById(R.id.map); if (map == null) { map = ((MapView) findViewById(R.id.map)).getMap(); } 

I didn't have luck with the map view either. 地图视图也没有运气。
I did have luck with the MapFragment. 我确实幸运地使用了MapFragment。

Try this: 尝试这个:

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));
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM