Switching basemaps in Android app not working properly

1553
7
Jump to solution
07-27-2016 08:15 AM
LageplanGöttingen
New Contributor III

Hi,

we have a problem with switching basemaps in our Android app.

We have two different types of basemaps (both are ArcGISTiledMapServiceLayers, based on MapServices published to our ArcGIS Server).

Initially, the map is loaded with the first basemap (basemapOne) on top of it:

ArcGISTiledMapServiceLayer baseMapOne = new ArcGISTiledMapServiceLayer(basemapURL1);

map.addLayer(baseMapOne);

However, the user can toggle a switch to change to the other basemap.

We have implemented this as follows (layer number 0 is the first layer, i.e. the basemap):

map.getLayer(0).recycle(); 

map.removeLayer(0); 

if (...basemapOne was switched on....) {

map.addLayer(new ArcGISTiledMapServiceLayer(basemapURL1), 0);

} else {

map.addLayer(new ArcGISTiledMapServiceLayer(basemapURL2), 0);

}

Sometimes this works without problems, especially if we only just started the app. But if we then, for example, press the home button and thus pause the map, reopen it, and try to switch the basemap, nothing happens - the basemap we try to remove remains visible. Sometimes, we can see a few single tiles of the second basemap "shining through" , but that's all.

The only thing that helps in this case is to clear the app from memory, or to completely close it by using the back button. If we then open it again, switching basemaps usually works again (but sometimes not even then). It seems that the old tiles are still cached somehow, or not cleared from memory when calling "map.removeLayer". Or could it have to do with the fact that we use

getSharedPreferences(

   "mapPreference", 0).edit().putString("mapState", map.retainState()).apply();

to save the map state in onPause(), and map.restoreState(mapState) in onResume ?

By the way, the same problem appears if we don't use "removeLayer" and "addLayer" but instead setVisibility(true/false).

Any ideas how to solve the problems? Thank you!

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
AlexanderNohe1
Regular Contributor II

I have noticed that your onResume does not account for any existing layers in the map.  Therefore, you were adding a layer over top of your baselayer.  I went and added a small check and this seemed to resolve the issue:

@Override
public void onResume() {

   super.onResume();

   Log.d("SwitchBasemap", "onResume");

   ArcGISTiledMapServiceLayer baseMap = new ArcGISTiledMapServiceLayer(getString(R.string.basemapURL1));

   map = (MapView) findViewById(R.id.map);
   map.unpause();
   map.setAllowRotationByPinch(true);
   map.setMaxExtent(new Envelope(1102008.94, 6711653.74, 1110493.45, 6723119.29));
   map.setMinScale(35000);

  if (map.getLayers().length > 0) {

   map.removeLayer(0);
   map.addLayer(baseMap, 0);
   }

   else {

   map.addLayer(baseMap, 0);
   }

}

Please let me know if this helps.

View solution in original post

7 Replies
AlexanderNohe1
Regular Contributor II

I do not believe that retainState is the issue here as according to the documentation, it:

MapView | ArcGIS Android 10.2.8 API

"Saves the coordinates of the center of the map, the current map resolution, and the LocationDisplayManager state"

This should not affect the layers that are showing.

Is there a chance that an app with a higher priority that needs memory is recycling your app and you are going back to the onCreate method or is it possible that your app is hitting onRestart and then onStart since the activity may no longer be visible?

Here is a copy of the activity lifecycle again for reference:

State diagram for an Android Activity Lifecycle.

0 Kudos
LageplanGöttingen
New Contributor III

Thanks for your reply!

We just checked it again, but the problem indeed mostly happens after "onResume" is called, not after "onStart" or "onCreate". 

It happens even if there is still a lot of free memory available and no other apps are open.

0 Kudos
AlexanderNohe1
Regular Contributor II

Lageplan Göttingen

That seems odd.  Can you send me the smallest reproducible sample so I may test here in house and update you with the results I see?

LageplanGöttingen
New Contributor III

Okay, I have written a small example application that shows one of our basemaps, and if you click on the button, it switches to the other basemap. Again, this works well until I press the home button. If I then reopen the app (which was not destroyed, just paused), I can no longer switch basemaps.

You can download the Android Studio project here: http://www.filedropper.com/switchbasemap

It only contains one activity, "BasemapActivity".

If for some reason you cannot compile the app from the source code I provided, please let me know and I can send you a signed APK file.

0 Kudos
AlexanderNohe1
Regular Contributor II

I am in the process of downloading the file as we speak.  I will update you as available.  I am in training the next two days so it may be a little difficult to find the time to test this.

AlexanderNohe1
Regular Contributor II

I have noticed that your onResume does not account for any existing layers in the map.  Therefore, you were adding a layer over top of your baselayer.  I went and added a small check and this seemed to resolve the issue:

@Override
public void onResume() {

   super.onResume();

   Log.d("SwitchBasemap", "onResume");

   ArcGISTiledMapServiceLayer baseMap = new ArcGISTiledMapServiceLayer(getString(R.string.basemapURL1));

   map = (MapView) findViewById(R.id.map);
   map.unpause();
   map.setAllowRotationByPinch(true);
   map.setMaxExtent(new Envelope(1102008.94, 6711653.74, 1110493.45, 6723119.29));
   map.setMinScale(35000);

  if (map.getLayers().length > 0) {

   map.removeLayer(0);
   map.addLayer(baseMap, 0);
   }

   else {

   map.addLayer(baseMap, 0);
   }

}

Please let me know if this helps.

View solution in original post

LageplanGöttingen
New Contributor III

Great!! This solved our problem.

Thanks a lot for your help!