Android 在碎片上添加带有开放街道地图的标记

Android 在碎片上添加带有开放街道地图的标记,android,openstreetmap,osmdroid,Android,Openstreetmap,Osmdroid,我试图使用带有片段的开放街道地图,但当我调用“addMarker”函数时,应用程序关闭。我试图修改函数,但没有成功。我的目标是在地图上添加标记。我认为这是因为这个函数正在获取一个活动的上下文,但我无法让它获取片段的上下文 public class MapFragment extends Fragment implements LocationListener { private static MapFragment INSTANCE = null; View view; MapView ma

我试图使用带有片段的开放街道地图,但当我调用“addMarker”函数时,应用程序关闭。我试图修改函数,但没有成功。我的目标是在地图上添加标记。我认为这是因为这个函数正在获取一个活动的上下文,但我无法让它获取片段的上下文

public class MapFragment extends Fragment implements LocationListener {

private static MapFragment INSTANCE = null;
View view;

MapView map = null;
private MapView osm;
private MapController mc;
private LocationManager locationManager;
private CompassOverlay compassOverlay;
private DirectedLocationOverlay locationOverlay;
private static final int PERMISSAO_REQUERIDA = 1;


public MapFragment() {
    // Required empty public constructor
}

public static MapFragment getINSTANCE(){
    if(INSTANCE==null)
        INSTANCE = new MapFragment();
        return INSTANCE;

}

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


}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    view = inflater.inflate(R.layout.fragment_map, container, false);
    //return view;


    if (Build.VERSION.SDK_INT >= M) {
        if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            String[] permissoes = {Manifest.permission.INTERNET, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION};
            requestPermissions(permissoes, PERMISSAO_REQUERIDA);
        }
    }
    //onde mostra a imagem do mapa
    Context ctx = getActivity().getApplicationContext();
    Configuration.getInstance().load(ctx, PreferenceManager.getDefaultSharedPreferences(ctx));
    MapView osm = view.findViewById(R.id.map);
    osm.setTileSource(TileSourceFactory.MAPNIK);
    osm.setBuiltInZoomControls(true);
    osm.setMultiTouchControls(true);

    mc = (MapController) osm.getController();
    mc.setZoom(15);


    //GeoPoint center = new GeoPoint(-5.1251,-38.3640);
    //mc.animateTo(center);
    //addMarker(center);

    locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, this);

    /* grade no mapa
    LatLonGridlineOverlay2 overlay = new LatLonGridlineOverlay2();
    osm.getOverlays().add(overlay);
    */

    osm.setMapListener(new MapListener() {
        @Override
        public boolean onScroll(ScrollEvent event) {
            Log.i("Script", "onScroll()");
            return false;
        }

        @Override
        public boolean onZoom(ZoomEvent event) {
            Log.i("Script", "onZoom()");
            return false;
        }
    });


    return view;
}

public void addMarker (GeoPoint center){
    Marker marker = new Marker(osm);
    marker.setPosition(center);
    marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
    marker.setIcon(getResources().getDrawable(R.drawable.fire));
    osm.getOverlays().clear();
    osm.getOverlays().add(marker);
    osm.invalidate();
    marker.setTitle("Sua Localização");
}


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case PERMISSAO_REQUERIDA: {
            // Se a solicitação de permissão foi cancelada o array vem vazio.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permissão cedida, recria a activity para carregar o mapa, só será executado uma vez
                getActivity().recreate();

            }

        }
    }
}

public void onResume() {
    super.onResume();

}


public void onPause(){
    super.onPause();
}

@Override
public void onLocationChanged(Location location) {
    GeoPoint center = new GeoPoint(location.getLatitude(), location.getLongitude());

    mc.animateTo(center);
    addMarker(center);

}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {

}

@Override
public void onProviderEnabled(String provider) {

}

@Override
public void onProviderDisabled(String provider) {

}
@Override
public void onDestroy(){
    super.onDestroy();
    if (locationManager != null){
        locationManager.removeUpdates(this);
    }

}
}

返回此错误:

Process: ep.tech.myapp, PID: 15419
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context org.osmdroid.views.MapView.getContext()' on a null object reference
    at org.osmdroid.views.overlay.Marker.<init>(Marker.java:93)
    at ep.tech.myapp.Fragments.MapFragment.addMarker(MapFragment.java:132)
    at ep.tech.myapp.Fragments.MapFragment.onLocationChanged(MapFragment.java:175)
    at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:292)
    at android.location.LocationManager$ListenerTransport.-wrap0(Unknown Source:0)
    at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:237)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6543)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:440)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:810)
流程:ep.tech.myapp,PID:15419
java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“android.content.Context org.osmdroid.views.MapView.getContext()”
位于org.osmdroid.views.overlay.Marker.(Marker.java:93)
位于ep.tech.myapp.Fragments.MapFragment.addMarker(MapFragment.java:132)
在ep.tech.myapp.Fragments.MapFragment.onLocationChanged(MapFragment.java:175)中
位于android.location.LocationManager$ListenerTransport.\u handleMessage(LocationManager.java:292)
位于android.location.LocationManager$ListenerTransport.-wrap0(未知来源:0)
位于android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:237)
位于android.os.Handler.dispatchMessage(Handler.java:106)
位于android.os.Looper.loop(Looper.java:164)
位于android.app.ActivityThread.main(ActivityThread.java:6543)
位于java.lang.reflect.Method.invoke(本机方法)
位于com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:440)
位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:810)
在onCreateView()中,您缺少findViewById:

osm= (MapView) view.findViewById(R.id.your_map_id);
在onCreateView()中,缺少findViewById:

osm= (MapView) view.findViewById(R.id.your_map_id);

实际上,我在从XML布局加载固定的OSMDroid映射视图时遇到了问题。它简直崩溃了

下面是片段_test.xml的样子:

<androidx.constraintlayout.widget.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:id="@+id/osm_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.osmdroid.views.MapView
    android:id="@+id/osmap"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
但它不起作用。我所做的只是一种变通办法。我从XML中删除了静态MapView,并在onCreateView中动态添加了MapView。现在它可以工作了。也许这个解决方案对任何人都有帮助

这就是新fragment_test.xml的样子(只是空容器):


实际上,我在从XML布局加载固定的OSMDroid映射视图时遇到了问题。它简直崩溃了

下面是片段_test.xml的样子:

<androidx.constraintlayout.widget.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:id="@+id/osm_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.osmdroid.views.MapView
    android:id="@+id/osmap"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
但它不起作用。我所做的只是一种变通办法。我从XML中删除了静态MapView,并在onCreateView中动态添加了MapView。现在它可以工作了。也许这个解决方案对任何人都有帮助

这就是新fragment_test.xml的样子(只是空容器):


请随时告诉我您是否卡住了。请随时告诉我您是否卡住了。您已经得到了正确的答案,但值得指出的是,在
中,尝试在空对象引用上调用虚拟方法“android.content.Context org.osmdroid.views.MapView.getContext()”
中的“空对象”是
MapView
getContext()
是被调用的方法,因此
MapView
是空对象。这就是你阅读崩溃日志的方式。你已经得到了正确的答案,但值得指出的是,在
中,在空对象引用上尝试调用虚拟方法“android.content.Context org.osmdroid.views.MapView.getContext()”
中,“空对象”是
MapView
getContext()
是被调用的方法,因此
MapView
是空对象。这就是你阅读类似崩溃日志的方式。
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    Context ctx = getActivity();

    View view = inflater.inflate(R.layout.fragment_test, container, false);

    Configuration.getInstance().load(ctx, PreferenceManager.getDefaultSharedPreferences(ctx));

    mMapView = new MapView(ctx);
    ((ConstraintLayout) view.findViewById(R.id.osm_fragment)).addView(mMapView);
    mMapView.setTileSource(TileSourceFactory.OpenTopo);