可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am using com.google.android.gms:play-services-maps:7.5.0
version of Google Maps services. When trying to call the below I get java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.SupportMapFragment.getMapAsync(com.google.android.gms.maps.OnMapReadyCallback)' on a null object reference
.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
SupportMapFragment mapFragment = (SupportMapFragment) getActivity().getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this); //error
return inflater.inflate(R.layout.fragment_example_map, container, false);
}
fragment_example_map.xml file:
<FrameLayout 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="app.ExampleMap">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
回答1:
You are attempting to find a fragment before it exists. You indicate that the layout that has the fragment is fragment_example_map.xml
. However, you are trying to find the map fragment before you inflate that layout file. This will not work.
Beyond that, you appear to be trying to get at the map fragment from inside another fragment, in that fragment's onCreateView()
method. I do not know why you are nesting fragments here, as it seems like it will make your code more complex and more fragile for no obvious benefit.
回答2:
My comment in maps with fragment , first you should refrenece your view as you will call something from it , this is why I inflate my view first
View view = inflater.inflate(R.layout.activity_maps, null, false);
Second call child fragment manager this.getChildFragmentManager()
instead of getActivity().getSupportFragmentManager()
Here is the full example to view map
import android.os.Bundle;
import android.support.annotation.Nullable;
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.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class ClinicFragment extends Fragment implements OnMapReadyCallback {
private GoogleMap mMap;
public static ClinicFragment newInstance() {
ClinicFragment fragment = new ClinicFragment();
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_maps, null, false);
SupportMapFragment mapFragment = (SupportMapFragment) this.getChildFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
return view;
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
required permission
<permission
android:name="your.package.name.permission.MAPS_RECEIVE"
android:protectionLevel="signature" />
<uses-permission android:name="your.package.name.permission.MAPS_RECEIVE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
plus feature element
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
most import google maps key
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="your_key_here" />
Update add this meta data if you face Error inflating class fragment
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="your_key_here" />
summery for mainfest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.package.name" >
// permission here
<application
android:name=".Activities.MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
// feature element
// maps key
</application>
</manifest>
activity_maps.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.imaadv.leaynik.ClinicFragment" />
回答3:
use getChildFragmentManager()
in place of getActivity().getSupportFragmentManager()
in the fragment.
like:
SupportMapFragment mapFragment = (SupportMapFragment)getChildFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
回答4:
If your are using android:name="com.google.android.gms.maps.MapFragment"
in your fragment then change your code with:
MapFragment mapFragment1 = (MapFragment)getFragmentManager().findFragmentById(R.id.map);
mapFragment1.getMapAsync(this);
However if your are using android:name="com.google.android.gms.maps.SupportMapFragment"
in your fragment then use this code:
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
回答5:
this works for me:
SupportMapFragment mapFragment = (SupportMapFragment)getChildFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
回答6:
Depending on Android version or SDK version 5 and above use getChildFragmentManager() and below it used getFragmentManager().
回答7:
use this.
GoogleMap gooleMap;
((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap map) {
googleMap = map;
}
回答8:
getFragmentManager() will may not be work when you are using map inside fragment. You have to use getChildFragmentManager().
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.fragment_track_order_map_fragment);
mapFragment.getMapAsync(this);
and below is my xml declaration
<fragment
android:id="@+id/fragment_track_order_map_fragment"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
also you need to implements OnMapReadyCallback in your fragment .
回答9:
The simple answer is if you want to add Map Fragment this
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/fragment_home" />
In to your fragment : like this layout
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.earthreport.fragments.HomeFragment"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="81dp">
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="@id/guideline4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/guideline3"
tools:layout="@layout/fragment_home" />
</android.support.constraint.ConstraintLayout>
Then you have to to add this line after the inflating the fragment like this
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Find a reference to the {@link ListView} in the layout
// Inflate the layout for this fragment
// To get the referance we don't have findviewbyId
// method in fragment so we use view
View view = inflater.inflate(R.layout.fragment_home, container, false);
SupportMapFragment mapFragment = (SupportMapFragment)
this.getChildFragmentManager()
.findFragmentById(R.id.map)
mapFragment.getMapAsync(this);
.....
Into your Activity: like this layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:context="package com.example.android.map" />
</android.support.constraint.ConstraintLayout>
then you have to add this chunk of code.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map_activity);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
Correct me if im wrong but always add map fragment after inflating the layout or set the content view.
回答10:
Faced the same problem. Since you are using the Map fragment within a Fragment use getChildFragmentManager() instead of getActivity().getFragmentManager() or getFragmentManager()
回答11:
replace this code
<fragment
android:name="com.google.android.gms.maps.MapFragment"
android:id="@+id/map"
android:layout_width="fill_parent"
android:layout_height="400dp" />
and
if (googleMap == null) {
mapFrag = (MapFragment)getFragmentManager().findFragmentById(R.id.map);
mapFrag.getMapAsync(this);
}else{
GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
}
回答12:
Just Call supportMapFragment.getMapAsync(this);
in onResume
in your Activity
回答13:
I was using SupportMapFragment and in XML I defined MapFragment name attribute
android:name="com.google.android.gms.maps.MapFragment"
so I replaced the code with SupportMapFragment and it started working fine
android:name="com.google.android.gms.maps.SupportMapFragment"