Detect if the OSM Mapview is still loading or not in android
Asked Answered
K

4

8

I have included Open Street Maps in my android application. In the mapview, user should be able to capture the screen after the map is fully loaded. But currently user can capture the image even when the mapview is still loading. Can someone tell me how to detect when the mapview is fully loaded?

Below is my code to load the mapview:

public class MainActivity extends Activity  {
    MapView mapView;
    MyLocationOverlay myLocationOverlay = null;
    ArrayList<OverlayItem> anotherOverlayItemArray;
    protected ItemizedOverlayWithBubble<ExtendedOverlayItem> itineraryMarkers;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mapView = (MapView) findViewById(R.id.mapview);

        final ArrayList<ExtendedOverlayItem> waypointsItems = new ArrayList<ExtendedOverlayItem>();
        itineraryMarkers = new ItemizedOverlayWithBubble<ExtendedOverlayItem>(this, waypointsItems, mapView, new ViaPointInfoWindow(R.layout.itinerary_bubble, mapView));
        mapView.getOverlays().add(itineraryMarkers);

        mapView.setTileSource(TileSourceFactory.MAPNIK);
        mapView.setBuiltInZoomControls(true);
        MapController mapController = mapView.getController();
        mapController.setZoom(1);
        GeoPoint point2 = new GeoPoint(51496994, -134733);
        mapController.setCenter(point2);

        Drawable marker=getResources().getDrawable(android.R.drawable.star_big_on);
        GeoPoint myPoint1 = new GeoPoint(0*1000000, 0*1000000);
        ExtendedOverlayItem overlayItem = new ExtendedOverlayItem("Title Test Loc", "Desc", myPoint1, this);
        overlayItem.setMarkerHotspot(OverlayItem.HotspotPlace.BOTTOM_CENTER);
        overlayItem.setMarker(marker);
        overlayItem.setRelatedObject(0);
        itineraryMarkers.addItem(overlayItem);
        mapView.invalidate();



        myLocationOverlay = new MyLocationOverlay(this, mapView);
        mapView.getOverlays().add(myLocationOverlay);
        myLocationOverlay.enableMyLocation();

        myLocationOverlay.runOnFirstFix(new Runnable() {
            public void run() {
             mapView.getController().animateTo(myLocationOverlay.getMyLocation());
               } 
           });


    }

    @Override
     protected void onResume() {
      // TODO Auto-generated method stub
      super.onResume();
      myLocationOverlay.enableMyLocation();
      myLocationOverlay.enableCompass();
      myLocationOverlay.enableFollowLocation();
     } 

     @Override
     protected void onPause() {
      // TODO Auto-generated method stub
      super.onPause();
      myLocationOverlay.disableMyLocation();
      myLocationOverlay.disableCompass();
      myLocationOverlay.disableFollowLocation();
     }
Kuhl answered 13/6, 2013 at 4:38 Comment(0)
K
1

I created a class named "MyTileOverlay" by extending TilesOverlay and it contins this class:

https://code.google.com/p/osmdroid/source/browse/trunk/osmdroid-android/src/main/java/org/osmdroid/views/overlay/TilesOverlay.java?r=1086

Then when setting up the mapview, I do this:

this.mTilesOverlay = new MyTileOverlay(mProvider, this.getBaseContext());

As instructed by kurtzmarc, I used handleTile() to check whether all tiles are being loaded or not:

@Override
        public void handleTile(final Canvas pCanvas, final int pTileSizePx,
                final MapTile pTile, final int pX, final int pY) {
            Drawable currentMapTile = mTileProvider.getMapTile(pTile);
            if (currentMapTile == null) {
                currentMapTile = getLoadingTile();
                Log.d("Tile Null", "Null");
            } else {

                Log.d("Tile Not Null", "Not Null");
            }

            if (currentMapTile != null) {
                mTileRect.set(pX * pTileSizePx, pY * pTileSizePx, pX
                        * pTileSizePx + pTileSizePx, pY * pTileSizePx
                        + pTileSizePx);
                onTileReadyToDraw(pCanvas, currentMapTile, mTileRect);
            }

            if (DEBUGMODE) {
                mTileRect.set(pX * pTileSizePx, pY * pTileSizePx, pX
                        * pTileSizePx + pTileSizePx, pY * pTileSizePx
                        + pTileSizePx);
                mTileRect.offset(-mWorldSize_2, -mWorldSize_2);
                pCanvas.drawText(pTile.toString(), mTileRect.left + 1,
                        mTileRect.top + mDebugPaint.getTextSize(),
                        mDebugPaint);
                pCanvas.drawLine(mTileRect.left, mTileRect.top,
                        mTileRect.right, mTileRect.top, mDebugPaint);
                pCanvas.drawLine(mTileRect.left, mTileRect.top,
                        mTileRect.left, mTileRect.bottom, mDebugPaint);
            }
        }

This method ensures whether the loading procedure is finalized or not:

@Override
            public void finaliseLoop() {
                Log.d("Loop Finalized", "Finalized");
            }

I can also use this method to identify whether all tiles have been loaded or not:

public int getLoadingBackgroundColor() {
            return mLoadingBackgroundColor;
        }

Hope this help someone!

Kuhl answered 27/6, 2013 at 7:57 Comment(0)
T
4

Take a look at TilesOverlay and the TileLooper implementation. This is what we use to load and then draw each tile on the screen. In handleTile(...) we attempt to get the tile from the tile provider mTileProvider.getMapTile(pTile). If that returns a Drawable then the tile is loaded, if not it will return null.

A simple way to do this is to extend TilesOverlay, override drawTiles(...) and call your own TileLooper before calling super.drawTiles(...) that will check to see if all the tiles that get passed to handleTile(...) are not null. To use your TilesOverlay call mMapView.getOverlayManager().setTilesOverlay(myTilesOverlay).

Token answered 26/6, 2013 at 13:9 Comment(2)
Thank you very much, could you please provide some sample codes for this?Kuhl
I was able to come up a set of codes like this: public class Tiles extends TilesOverlay{ public Tiles(MapTileProviderBase aTileProvider, Context aContext) { super(aTileProvider, aContext); // TODO Auto-generated constructor stub } @Override public void drawTiles(Canvas c, int zoomLevel, int tileSizePx, Rect viewPort) { // TODO Auto-generated method stub TileLooper tileloop; tileloop.handleTile(arg0, arg1, arg2, arg3, arg4) super.drawTiles(c, zoomLevel, tileSizePx, viewPort); } } please let me know how to proceed. Thanks!Kuhl
A
2

Since osmdroid API 6.1.0, it's quite easy:

// check completeness of map tiles
TileStates tileStates = mapView.getOverlayManager().getTilesOverlay().getTileStates();

// evaluate the tile states
if (tileStates.getTotal() == tileStates.getUpToDate())
{
    // map is loaded completely

}
else
{
    // loading is still in progress

}

/* meaning of TileStates
    .getUpToDate()   not expired yet
    .getExpired()    expired
    .getScaled()     computed during zoom
    .getNotFound()   default grey tile
    ---------------------------------------
    .getTotal()      sum of all above
*/
Albinus answered 29/11, 2019 at 13:24 Comment(0)
K
1

I created a class named "MyTileOverlay" by extending TilesOverlay and it contins this class:

https://code.google.com/p/osmdroid/source/browse/trunk/osmdroid-android/src/main/java/org/osmdroid/views/overlay/TilesOverlay.java?r=1086

Then when setting up the mapview, I do this:

this.mTilesOverlay = new MyTileOverlay(mProvider, this.getBaseContext());

As instructed by kurtzmarc, I used handleTile() to check whether all tiles are being loaded or not:

@Override
        public void handleTile(final Canvas pCanvas, final int pTileSizePx,
                final MapTile pTile, final int pX, final int pY) {
            Drawable currentMapTile = mTileProvider.getMapTile(pTile);
            if (currentMapTile == null) {
                currentMapTile = getLoadingTile();
                Log.d("Tile Null", "Null");
            } else {

                Log.d("Tile Not Null", "Not Null");
            }

            if (currentMapTile != null) {
                mTileRect.set(pX * pTileSizePx, pY * pTileSizePx, pX
                        * pTileSizePx + pTileSizePx, pY * pTileSizePx
                        + pTileSizePx);
                onTileReadyToDraw(pCanvas, currentMapTile, mTileRect);
            }

            if (DEBUGMODE) {
                mTileRect.set(pX * pTileSizePx, pY * pTileSizePx, pX
                        * pTileSizePx + pTileSizePx, pY * pTileSizePx
                        + pTileSizePx);
                mTileRect.offset(-mWorldSize_2, -mWorldSize_2);
                pCanvas.drawText(pTile.toString(), mTileRect.left + 1,
                        mTileRect.top + mDebugPaint.getTextSize(),
                        mDebugPaint);
                pCanvas.drawLine(mTileRect.left, mTileRect.top,
                        mTileRect.right, mTileRect.top, mDebugPaint);
                pCanvas.drawLine(mTileRect.left, mTileRect.top,
                        mTileRect.left, mTileRect.bottom, mDebugPaint);
            }
        }

This method ensures whether the loading procedure is finalized or not:

@Override
            public void finaliseLoop() {
                Log.d("Loop Finalized", "Finalized");
            }

I can also use this method to identify whether all tiles have been loaded or not:

public int getLoadingBackgroundColor() {
            return mLoadingBackgroundColor;
        }

Hope this help someone!

Kuhl answered 27/6, 2013 at 7:57 Comment(0)
R
0

You can pass a runnable callback to the TileStates class of the tile overlay:

overlayManager.tilesOverlay.tileStates.runAfters.add(Runnable {
        // Tile loading completed
    })

Works quite well.

Riches answered 6/5, 2022 at 12:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.