【问题标题】:Google Maps Fragment returning null inside a fragmentGoogle Maps Fragment 在片段内返回 null
【发布时间】:2014-10-28 12:28:08
【问题描述】:

所以我有一个包含地图片段的空片段。每当我尝试激活包含地图的片段时,我的应用程序崩溃并在此行返回空指针错误:

map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
                .getMap();

完整的错误信息:

java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.GoogleMap com.google.android.gms.maps.MapFragment.getMap()' on a null object reference
            at com.collusion.serviceassistant.ReturnVisitDetails.onViewCreated(ReturnVisitDetails.java:39)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:904)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
            at android.app.BackStackRecord.run(BackStackRecord.java:684)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1447)
            at android.app.FragmentManagerImpl$1.run(FragmentManager.java:443)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)

这是我的片段代码:

import android.app.Activity;
import android.app.Dialog;
import android.net.Uri;
import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;


public class ReturnVisitDetails extends Fragment {

    static final LatLng HAMBURG = new LatLng(53.558, 9.927);
    static final LatLng KIEL = new LatLng(53.551, 9.993);
    private GoogleMap map;
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_return_visit_add, container, false);
        return rootView;
    }

    public void onViewCreated(View view, Bundle savedInstanceState)
    {
        // Get a handle to the Map Fragment
        map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
                .getMap();
        Marker hamburg = map.addMarker(new MarkerOptions().position(HAMBURG)
                .title("Hamburg"));
        Marker kiel = map.addMarker(new MarkerOptions()
                .position(KIEL)
                .title("Kiel")
                .snippet("Kiel is cool")
                .icon(BitmapDescriptorFactory
                        .fromResource(R.drawable.ic_launcher)));

        // Move the camera instantly to hamburg with a zoom of 15.
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(HAMBURG, 15));

        // Zoom in, animating the camera.
        map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);
    }
}

还有我的父片段 XML 布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.collusion.serviceassistant.ReturnVisitDetails"
    android:background="#009688">


    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.MapFragment" />

</RelativeLayout>

有人知道为什么地图片段返回 null 吗?

编辑:所以现在我有这个代码来初始化地图:

MapFragment mapFragment = new MapFragment();
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        transaction.add(R.id.rl_map_container, mapFragment).commit();
        map = mapFragment.getMap();
        Marker hamburg = map.addMarker(new MarkerOptions().position(HAMBURG)
                .title("Hamburg"));
        Marker kiel = map.addMarker(new MarkerOptions()
                .position(KIEL)
                .title("Kiel")
                .snippet("Kiel is cool")
                .icon(BitmapDescriptorFactory
                        .fromResource(R.drawable.ic_launcher)));

        // Move the camera instantly to hamburg with a zoom of 15.
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(HAMBURG, 15));

        // Zoom in, animating the camera.
        map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);

而且它仍然返回一个空指针值

【问题讨论】:

  • 您已将此应用添加到您的 Google 控制台?
  • 是的。这与我使用调试证书有关吗?我只将我的发布证书密钥添加到清单中
  • 不应该没问题,在真实设备上测试,对吗?我会发布我的代码。

标签: android google-maps android-fragments


【解决方案1】:

我已经解决了这个问题。 当我有一个viewpager时这一行:

mMap = ((SupportMapFragment) MainActivity.fragmentManager
                .findFragmentById(R.id.mapView)).getMap();

你必须改成这样:

  mMap = ((SupportMapFragment) getChildFragmentManager()
            .findFragmentById(R.id.mapView)).getMap();

【讨论】:

  • 你结束了我朋友 8 小时的痛苦 :)
  • 两年后仍然在挽救生命
【解决方案2】:

您的类从 Fragment 扩展而来,并且您使用的是在布局中声明的 Fragment,但嵌套片段仅在动态添加时才有效。

所以,你有两个选择:

1) 从FragmentAcivity 扩展而不是Fragment 并应用正确的方法。

2) 动态添加Fragment,如下:

//返回访问详情

MapFragment mapFragment = new MapFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.rl_map_container, mapFragment).commit();

//布局

<FrameLayout
        android:id="@+id/rl_map_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

--已更新--

Fragment 中使用谷歌地图的完整示例:

//TestFragmentActivity

public class TestFragmentActivity extends android.support.v4.app.FragmentActivity {

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

}

//测试片段

public class TestFragment extends android.support.v4.app.Fragment {

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

        CustomMapFragment mapFragment = new CustomMapFragment();
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        transaction.add(R.id.map_container, mapFragment).commit();
        return rootView;
    }

}

//自定义地图片段

public class CustomMapFragment extends com.google.android.gms.maps.SupportMapFragment {

    private final LatLng HAMBURG = new LatLng(53.558, 9.927);

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        GoogleMap googleMap = getMap();
        googleMap.addMarker(new MarkerOptions().position(HAMBURG).title("Hamburg"));
        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(HAMBURG, 15));
        googleMap.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);
    }

}

//test_fragment_activity.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <fragment
        android:id="@+id/map"
        class="your_package.TestFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

//test_fragment.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/map_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

【讨论】:

  • 那么现在我该如何初始化地图并访问它呢?
  • @valbertos 谢谢你节省了我的时间 :) +1 :)
  • 为什么要在onActivityCreated()中获取地图?为什么不在 onCreate() 或 onCreateView() 中?注意:getMapAsync() ...
  • java.lang.IllegalArgumentException: No view found for id 0x7f0b005f (com.xxx.xxx:id/fragment_container) for fragment GMapFragment{425e9c10 #0 id=0x7f0b005f} 它不起作用。 CustomMapFragment 的布局是什么?你能分享更多信息吗?
  • 我投了赞成票,因为您提到了一种动态添加它的出色方法。 .
【解决方案3】:

当我尝试将我的 Eclipse 项目移植到 Android Studio 项目时,我遇到了这个问题。

java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.GoogleMap com.google.android.gms.maps.SupportMapFragment.getMap()' on a null object reference

我将它与这样的片段活动一起使用:

((SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.mapToday)).getMap();

但是,问题是,早些时候我使用的是特定版本的 Google Play 服务 (4.3.23)。

但 Gradle 构建选择的是最新版本 (compile 'com.google.android.gms:play-services:+')

我尝试了一些其他特定版本,例如 (6.1.71)。但还是给出了空点异常。

我使用了与以前相同的旧版本,并且可以正常工作。

compile 'com.google.android.gms:play-services:4.3.23'

这对我来说是一个临时解决方案。但是,当我需要更新到 新的播放服务库。

似乎没有可用于 Gradle 构建的此版本的特定地图库 当我这样尝试时:

compile 'com.google.android.gms:play-services-maps:4.3.23'

【讨论】:

【解决方案4】:

我在这方面搜索了很多线程,因为我在使用旧的 google play 服务时遇到了同样的问题。正如维克多所说,你的类从片段扩展,它必须使用布局中定义的另一个片段,所以最好的方法是使用getChildFragmentManager() 而不是getSupportFragmentManager()

还有getMap() method is deprecated 现在在谷歌文档中提到。请参阅此以获取更多信息:- https://developers.google.com/android/reference/com/google/android/gms/maps/MapFragment.html#getMap()

以下是我在各种旧播放服务设备上测试的工作代码。如果设备具有较旧的 google play 服务并且GoogleMap 的对象返回 null,这将生成默认消息:

class MyFragment extends Fragment
{
      SupportMapFragment myMapFragment;
    GoogleMap myMap;
    View convertView;
    FragmentManager fm;
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {

    convertView=inflater.inflate(R.layout.mymap,null);
    fm=getChildFragmentManager();
        myMapFragment=(SupportMapFragment) fm.findFragmentById(R.id.myMapId);


        // here instead of using getMap(), we are using getMapAsync() which returns a callback and shows map only when it gets ready.
        //it automatically checks for null pointer or older play services version, getMap() is deprecated as mentioned in google docs.


        myMapFragment.getMapAsync(new OnMapReadyCallback() {

            @Override
            public void onMapReady(GoogleMap googlemap) {
                // TODO Auto-generated method stub
                myMap=googlemap;
                startMap();
            }
        });


    return convertView;
    }

}

请参阅此主题以获取更多信息。

【讨论】:

    【解决方案5】:

    这可能是迁移到 21 的目标 sdk 版本的问题吗?如果是这样,您可能会对以下解决方案感兴趣:

    MapFragment or MapView getMap() returns null on Lollipop

    【讨论】:

    • 谢谢,这是我的问题。
    【解决方案6】:

    尝试使用 SupportMapFragment 而不是 MapFragment。这段代码适用于我的片段,刚刚尝试过:

    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    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.BitmapDescriptorFactory;
    import com.google.android.gms.maps.model.LatLng;
    import com.google.android.gms.maps.model.Marker;
    import com.google.android.gms.maps.model.MarkerOptions;
    
    public class MapFragment extends Fragment {
    
    private GoogleMap map;
    static final LatLng HAMBURG = new LatLng(53.558, 9.927);
    static final LatLng KIEL = new LatLng(53.551, 9.993);
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
    
        View rootView = inflater.inflate(R.layout.fragment_map, container,
                false);
    
        // Get a handle to the Map Fragment
        map = ((SupportMapFragment) getFragmentManager().findFragmentById(
                R.id.map)).getMap();
        Marker hamburg = map.addMarker(new MarkerOptions().position(HAMBURG)
                .title("Hamburg"));
        Marker kiel = map.addMarker(new MarkerOptions()
                .position(KIEL)
                .title("Kiel")
                .snippet("Kiel is cool")
                .icon(BitmapDescriptorFactory
                        .fromResource(R.drawable.ic_launcher)));
    
        // Move the camera instantly to hamburg with a zoom of 15.
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(HAMBURG, 15));
    
        // Zoom in, animating the camera.
        map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);
    
        return rootView;
    }
    }
    

    和你的布局:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >
    
    <fragment
        android:id="@+id/map"
        android:name="com.example.test.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment" />
    
    </RelativeLayout>
    

    【讨论】:

      【解决方案7】:

      问题可能与您的targetSdkVersion 高于所使用的Android Support Library 版本有关。

      这是我的情况,在我们一直从事的项目之一中,targetSdkVersion 是 21,而支持库版本是 19.0.0。 targetSdkVersion 更改为 19 可以解决问题。

      【讨论】:

        【解决方案8】:

        我可能会遇到同样的问题,但最后我可以解决这个错误。现在地图正在正确显示...

        => 在 onCreateView() 方法中的 Fragment 中调用 initilizeMap() 方法...

        => 声明全局变量,如 ,

        private GoogleMap googleMap;
        
         private void initilizeMap() {
            try {
        
                // Changing marker icon
                // marker.icon(BitmapDescriptorFactory.fromResource(R.drawable.my_marker_icon)));
        
                // adding marker
                if (googleMap == null) {
                    googleMap = ((MapFragment)getActivity().getFragmentManager()
                            .findFragmentById(R.id.map)).getMap();
        
                    // create marker
                    MarkerOptions marker = new MarkerOptions().position(
                            new LatLng(latitude, longitude)).title(
                            "YourCare");
        
                    // Changing marker icon
                    MarkerOptions icon = marker.icon(BitmapDescriptorFactory
                            .defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
                    // adding marker
        
                    LatLng latLng = new LatLng(latitude, longitude);
                    CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(
                            latLng, 15);
                    googleMap.animateCamera(cameraUpdate);
                    // locationManager.removeUpdates(this);
        
                    googleMap.addMarker(marker);
                    googleMap.setMyLocationEnabled(true);
                    // check if map is created successfully or not
                    if (googleMap == null) {
                        Toast.makeText(getActivity(),
                                "Sorry! unable to create maps", Toast.LENGTH_SHORT)
                                .show();
                    }
        
                }
            } catch (Exception e) {
                System.out.print("Error :" + e.getMessage());
            }
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-03-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-05
          • 2017-05-05
          • 1970-01-01
          相关资源
          最近更新 更多