RoktSe
RoktSe

Reputation: 469

Add marker with Open Street Map on Fragment

I'm trying to use the Open Street map with fragment, but when I call the "addMarker" function, the APP closes. I tried to modify the function but I was not successful. My objective is add marker on map. I think it's because this function is taking the context of an activity but I couldn't get it to take the context of the fragment.

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

}

}

Return this error:

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)

Upvotes: 0

Views: 1943

Answers (2)

basileus
basileus

Reputation: 453

I actually had problems loading fixed OSMDroid MapView from XML layout. It simply was crashing.

Here is how the fragment_test.xml looked like:

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

Code itself for loading MapView in Fragment, in onCreateView looked similar:

    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 = view.findViewById(R.id.osmap);
    mMapView.setTileSource(TileSourceFactory.OpenTopo);

But it didn't work. What I did, was a kind of workaround. I removed static MapView from XML and added MapView dynamically in onCreateView. And it works now. Perhaps this solution will help anyone?

This is how new fragment_test.xml looks like (just empty container):

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

and how onCreateView in Fragment looks like (adding MapView to empty container programatically):

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

Upvotes: 0

haresh
haresh

Reputation: 1420

Inside onCreateView() you are missing findViewById :

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

Upvotes: 2

Related Questions