Android 谷歌地图片段在片段内返回 null

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25653898/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:37:20  来源:igfitidea点击:

Google Maps Fragment returning null inside a fragment

androidgoogle-mapsandroid-fragments

提问by axtscz

So I have an empty fragment that contains a map fragment. Whenever I try to activate the fragment containing the map, my app crashes and returns a null pointer error on this line:

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

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

Full Error message:

完整的错误信息:

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.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)

Here is my fragment code:

这是我的片段代码:

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

And my parent fragment XML layout:

和我的父片段 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>

Anyone have an idea why the map fragment is returning null?

任何人都知道为什么地图片段返回空值?

EDIT: So now I have this code to initialize the map:

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

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

And it still returns a null pointer value

它仍然返回一个空指针值

采纳答案by kalan nawarathne

This issue happened to me when I tried to port my Eclipse project to Android Studio project.

当我尝试将我的 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

I used it with a Fragment Activity like this:

我将它与这样的 Fragment Activity 一起使用:

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

However, the problem was, earlier I was using a specific version of Google Play Services (4.3.23).

然而,问题是,之前我使用的是特定版本的 Google Play 服务 (4.3.23)。

But the Gradle build select the most recent version (compile 'com.google.android.gms:play-services:+')

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

I tried some other specific version like (6.1.71). But still gave null point exception.

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

I used the same old version as I used before and it worked.

我使用了与以前使用的相同的旧版本,并且有效。

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

This works for me as a temporary solution. However, this will be a problem when I need to update to a new play services library.

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

It seems that there is no specific map library with this version available for Gradle build when I try like this:

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

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

回答by Cabezas

I have solved the issue. this line when I have a viewpager:

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

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

you have to change to this:

你必须改成这样:

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

回答by Víctor Albertos

Your class extends from Fragment, and you are using a Fragmentdeclared in the layout, but nested fragment only work when they are added dynamically.

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

So, you have two options:

所以,你有两个选择:

1) Extending from FragmentAcivityinstead of Fragmentand applying the proper methods.

1)从FragmentAcivity代替Fragment和应用适当的方法进行扩展。

2) Add the Fragmentdynamically, as follow:

2)Fragment动态添加,如下:

//ReturnVisitDetails

//返回访问详情

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

//Layout

//布局

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

--UPDATED--

- 更新 -

A complete example to use Google Maps inside a Fragment:

在 a 中使用 Google 地图的完整示例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);
    }

}

//TestFragment

//测试片段

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

}

//CustomMapFragment

//自定义地图片段

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

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

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

回答by Mrigank

I searched for a lot of threads on this as I was having the same issue with older google play services. As Victor said that your class extends from fragment and it has to use another fragment defined in the layout, So best approach will be to use getChildFragmentManager()instead of getSupportFragmentManager().

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

Also getMap() method is deprecatednow as mentioned in google docs. Please refer this for more:- https://developers.google.com/android/reference/com/google/android/gms/maps/MapFragment.html#getMap()

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

Below is the working code I have tested on various devices of older play services. This will generate the default message in case of device having older google play services and in case object of GoogleMapreturns null:

以下是我在旧版播放服务的各种设备上测试的工作代码。如果设备具有较旧的 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;
    }

}

See this thread for more info.

有关更多信息,请参阅此线程。

回答by Rhisiart

Could this be an issue of migrating to a target sdk version of 21? If so, the following solution may be of interest to you:

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

MapFragment or MapView getMap() returns null on Lollipop

MapFragment 或 MapView getMap() 在 Lollipop 上返回 null

回答by user1282637

Try using SupportMapFragment instead of MapFragment. This code works for me for a Fragment, just tried it:

尝试使用 SupportMapFragment 而不是 MapFragment。这段代码适用于我的 Fragment,试了一下:

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

and your layout:

和你的布局:

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

回答by sathish

I can face same problem but finally i can solve that error.Now Map is Properly showing...

我可以面对同样的问题,但最后我可以解决那个错误。现在地图正确显示......

=> Call initilizeMap() Method in Fragment within a onCreateView() method...

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

=> Declare Global Variable like ,

=> 像这样声明全局变量,

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

}

回答by syntagma

The problem may be related to the fact that your targetSdkVersionis higher than the version of Android Support Library used.

该问题可能与您targetSdkVersion的版本高于所使用的 Android 支持库版本有关。

That was my case, in one of the projects we've been working on targetSdkVersionwas 21, while Support Library version was 19.0.0. Changing targetSdkVersionto 19 fixed the problem.

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