web-dev-qa-db-ja.com

フラグメント内でnullを返すGoogle Maps Fragment

そのため、マップフラグメントを含む空のフラグメントがあります。マップを含むフラグメントをアクティブにしようとすると、アプリがクラッシュし、次の行でnullポインターエラーが返されます。

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

そして、それはまだnullポインタ値を返します

18
axtscz

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 Services(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'
10
kalan

私は問題を解決しました。ビューページャーがある場合、この行:

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

これに変更する必要があります:

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

クラスはFragmentから拡張され、レイアウトで宣言されたFragmentを使用していますが、ネストされたフラグメントは動的に追加された場合にのみ機能します。

したがって、2つのオプションがあります。

1)FragmentAcivityの代わりにFragmentから拡張し、適切なメソッドを適用します。

2)次のように、Fragmentを動的に追加します。

// ReturnVisitDetails

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

-UPDATED-

Fragment内でGoogleマップを使用する完全な例:

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

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

古いGoogle Playサービスで同じ問題を抱えていたので、これに関する多くのスレッドを検索しました。ビクターがクラスはフラグメントから拡張し、レイアウトで定義された別のフラグメントを使用する必要があると言ったので、最善のアプローチはgetChildFragmentManager()の代わりにgetSupportFragmentManager()を使用することです。

また、Googleドキュメントに記載されている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;
    }

}

詳細については、このスレッドを参照してください。

8
Mrigank

これは21のターゲットSDKバージョンへの移行の問題ですか?その場合、次の解決策が興味を引く可能性があります。

MapFragmentまたはMapView getMap()はLollipopでnullを返します

7
Rhisiart

この問題は、targetSdkVersionがAndroidサポートライブラリが使用されているバージョンよりも高いバージョンであるという事実に関連している可能性があります。

私が取り組んでいたプロジェクトの1つでは、targetSdkVersionは21でしたが、サポートライブラリのバージョンは19.0.0でした。 targetSdkVersionを19に変更すると問題が修正されました。

0
syntagma

私は同じ問題に直面することができますが、最終的に私はそのエラーを解決することができます。現在マップは正しく表示されています...

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

}
0
sathish

MapFragmentの代わりにSupportMapFragmentを使用してみてください。このコードはフラグメントのために私のために機能します、ちょうど試してみました:

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