谷歌地图Android API V2:GoogleMap为空。

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

即使您不需要MapFragment,仍然需要一个MapActivity... - njzk2
你的意思是什么?你的意思是这个类不应该从Activity继承吗? - lyk
6个回答

3
这似乎是一个老问题,但我也遇到了同样的问题,尝试使用MapView。
假设你已经正确导入了Google Play服务库,你必须检查是否可以访问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();
}

如果您看到“SUCCESS”字样,则说明目前一切工作正常。同时,您还需要实现Activity生命周期方法,并在每个方法内调用对应的地图视图方法:

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

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


3

谢谢,你终于给了我一个线索,可以编程初始化地图,我真是太愚蠢了,竟然没注意到它 :)

有时候我们无法使用MapFragment(或SupportMapFragment类似的东西),比如当你想从片段中使用地图时!实际上,这在使用选项卡(ActionBar)时非常常见,模式是使用片段。因此,您可以为每个选项卡创建自己的片段,并在该片段中为地图填充布局,其中包含MapFragment的片段,效果很好,祝你好运!

现在,根据MapView规范,没有说不鼓励或弃用使用MapView的方式,那么我为什么不能使用它呢?我不想使用维护嵌套片段的黑客方法,而没有得到SDK支持(甚至最近的支持lib v13似乎存在错误,不支持从布局中嵌套片段),因此对我来说使用MapView变成了KISS。

下面是我使用布局膨胀的CustomMapFragment,它允许复杂布局和嵌入式地图,欢迎使用。您还可以扩展来自支持库而不是SDK的Fragment。

onCreateView()方法填充布局(只需提供自己的布局),并期望该布局具有视图组(相对布局,线性布局等)和ID为“mapViewHolder”的地方,在布局创建时将MapView附加到上面。活动必须实现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;
  }
}


1
MapFragment和MapView之间的一个区别是,你必须手动管理MapView的生命周期,而MapFragment会自行处理。
你必须从父Activity/Fragment的对应方法中调用以下方法。
onCreate(Bundle)
onResume()
onPause()
onDestroy()
onSaveInstanceState()
onLowMemory()

我在Android SDK管理器的Extras部分安装了Google Play服务示例中的RawMapViewDemoActivity,并进行了验证。
该示例一开始显示地图,当我注释掉mMapView.onXXX()的6行代码后,它显示了一个空白页面。
也许生命周期是大多数示例都使用MapFragment的原因。

为什么他们在v1和v2中都排除了MapActivity? - GPrimola

0

尝试这种方式:

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

你能告诉我你正在使用哪个最低的 API 吗? - GrIsHu
那么您应该使用 SupportMapFragment,因为 MapFragment 是针对 API 12 或更高版本的。这就是为什么它会抛出此异常的原因。 - GrIsHu
我正在使用MapView,而不是MapFragment。因为地图将占据整个屏幕,所以我不需要实现MapFragment。SDK版本是否影响MapView类的使用? - lyk
是的,SDK会影响MapView,这就是为什么。我认为你应该在POnlineMapView活动中扩展android.support.v4.app.FragmentActivity而不是Activity - GrIsHu
我真的很想避免使用Fragments,因为我不熟悉它...但我想我必须去探索一下它是如何工作的...那么如果我扩展Fragment Activity,我还能使用MapView吗? - lyk
显示剩余3条评论

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接