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
Google Maps Fragment returning null inside a fragment
提问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 Fragment
declared in the layout, but nested fragment only work when they are added dynamically.
您的类从 扩展Fragment
,并且您Fragment
在布局中使用了声明,但嵌套片段仅在动态添加时才有效。
So, you have two options:
所以,你有两个选择:
1) Extending from FragmentAcivity
instead of Fragment
and applying the proper methods.
1)从FragmentAcivity
代替Fragment
和应用适当的方法进行扩展。
2) Add the Fragment
dynamically, 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 deprecated
now 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 GoogleMap
returns 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 版本的问题吗?如果是这样,您可能会对以下解决方案感兴趣:
回答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 targetSdkVersion
is 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 targetSdkVersion
was 21, while Support Library version was 19.0.0. Changing targetSdkVersion
to 19 fixed the problem.
这就是我的情况,在我们一直从事的项目之一中targetSdkVersion
,支持库版本是 21,而支持库版本是 19.0.0。更改targetSdkVersion
为 19 解决了问题。