As a slight correction.
WebTiledlayer does not allow you to overrride getTileUrl and expect it to be called.
We are using a subclass of ServiceImageTiledLayer.
I have produced a simple example using your WebTiledLayer sample. The
If you change this line of code to use WebTiledLayer instead of my custom class, performance is just fine.
Using my custom class inherited from ServiceImageTiledLayer - well, I am still waiting for the map to refresh after 10 minutes. In addition, the runtime thread pool of ArcGIS gets all used up, so features like place search suggestion don't work.
final MyWebTiledLayer webTiledLayer= new MyWebTiledLayer(templateUri);
I have escalated the case with Esri support, but they are unlikely to find a solution without help from developers.
While this template could be used with either WebTiledLayer or a custom class, there are many that cannot. We use up to 60 template urls in our application.
Web Tiled Layer can only handle {row} {col} {level} as tags.
Notably it cannot handle TMS server, just because the y is upside down from your {row} tag.
It cannot handle quadkeys like in Bing Urls. I am aware there is a Bing Maps layer, but it only has three styles. It could not handle, for instance, the Ordnance Survey style for the UK.
It can't handle a bounding box query to create tiles from a WMS server that supports 900913 projection.
/* Copyright 2017 Esri
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.esri.arcgisruntime.sample.webtiledlayer;
import java.util.Arrays;
import java.util.List;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.esri.arcgisruntime.arcgisservices.TileInfo;
import com.esri.arcgisruntime.layers.WebTiledLayer;
import com.esri.arcgisruntime.loadable.LoadStatus;
import com.esri.arcgisruntime.mapping.ArcGISMap;
import com.esri.arcgisruntime.mapping.Basemap;
import com.esri.arcgisruntime.mapping.Viewpoint;
import com.esri.arcgisruntime.mapping.view.MapView;
public class MainActivity extends AppCompatActivity {
private MapView mMapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// access MapView from layout
mMapView = (MapView) findViewById(R.id.mapView);
// list of subdomains
List<String> subDomains = Arrays.asList("a", "b", "c", "d");
// url pattern
String templateUri = "http://services.thelist.tas.gov.au/arcgis/rest/services/Basemaps/Topographic/ImageServer/tile/{level}/{row}/{col}/";
// webtile layer
final MyWebTiledLayer webTiledLayer= new MyWebTiledLayer(templateUri);
webTiledLayer.loadAsync();
webTiledLayer.addDoneLoadingListener(new Runnable() {
@Override
public void run() {
if (webTiledLayer.getLoadStatus() == LoadStatus.LOADED) {
// use webtile layer as Basemap
ArcGISMap map = new ArcGISMap(new Basemap(webTiledLayer));
map.setInitialViewpoint(new Viewpoint(-42.106967,147.097578,577791));
mMapView.setMap(map);
TileInfo tinfo = webTiledLayer.getTileInfo();
Log.i("webtiledlayer","web tileinfo: " + tinfo);
// custom attributes
/*
webTiledLayer.setAttribution("Map tiles by <a href=\"http://stamen.com/\">Stamen Design</a>, " +
"under <a href=\"http://creativecommons.org/licenses/by/3.0\">CC BY 3.0</a>. " +
"Data by <a href=\"http://openstreetmap.org/\">OpenStreetMap</a>, " +
"under <a href=\"http://creativecommons.org/licenses/by-sa/3.0\">CC BY SA</a>.");
*/
}
}
});
}
@Override
protected void onPause() {
super.onPause();
// pause MapView
mMapView.pause();
}
@Override
protected void onResume() {
super.onResume();
// resume MapView
mMapView.resume();
}
@Override
protected void onDestroy() {
super.onDestroy();
// dispose MapView
mMapView.dispose();
}
}
package com.esri.arcgisruntime.sample.webtiledlayer;
import android.util.Log;
import com.esri.arcgisruntime.arcgisservices.LevelOfDetail;
import com.esri.arcgisruntime.arcgisservices.TileInfo;
import com.esri.arcgisruntime.data.TileKey;
import com.esri.arcgisruntime.geometry.Envelope;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.geometry.SpatialReferences;
import com.esri.arcgisruntime.layers.ServiceImageTiledLayer;
import com.esri.arcgisruntime.layers.WebTiledLayer;
import java.util.ArrayList;
public class MyWebTiledLayer extends ServiceImageTiledLayer {
private static final String TAG = MyWebTiledLayer.class.getSimpleName();
String baseurl="default";
public MyWebTiledLayer(String templateUri) {
super(CreateTileInfo(1,15,templateUri), new Envelope(-20037508.342789244, -20037508.342789244, 20037508.342789244, 20037508.342789244, SpatialReferences.getWebMercator()));
baseurl = templateUri;
TileInfo ours = getTileInfo();
Log.i(TAG,"ours: " + ours.getCompressionQuality() + ", " + ours.getDpi() + ", " + ours.getFormat()+ ", "
+ ours.getLevelsOfDetail() + ", " + ours.getOrigin() + ", " + ours.getSpatialReference() + ", " + ours.getTileHeight() + ", " + ours.getTileWidth()) ;
Log.i(TAG, "end of constructor");
}
@Override
public String getUri() {
return baseurl;
}
private static final int TILESIZE = 256;
private static final double INITIALRESOLUTION = 2 * Math.PI * 6378137 / TILESIZE;
static public double zresolution(int zoom) {
return INITIALRESOLUTION / Math.pow(2, zoom);
}
private static TileInfo CreateTileInfo(int minZoom, int maxZoom, String baseurl)
{
WebTiledLayer wlayer = new WebTiledLayer(baseurl);
TileInfo theirs =wlayer.getTileInfo();
Log.i(TAG, "their extent: " + wlayer.getFullExtent());
Log.i(TAG,"theirs: " + theirs.getCompressionQuality() + ", " + theirs.getDpi() + ", " + theirs.getFormat()+ ", "
+ theirs.getLevelsOfDetail() + ", " + theirs.getOrigin() + ", " + theirs.getSpatialReference() + ", " + theirs.getTileHeight() + ", " + theirs.getTileWidth()) ;
int dpi = 96;
ArrayList<LevelOfDetail> levels = new ArrayList<>();
for (int i = minZoom; i <= maxZoom; i++)
{
double resolution = zresolution(i);
double scale = resolution * dpi * 39.37;
LevelOfDetail l = new LevelOfDetail(i, resolution, scale);
levels.add(l);
LevelOfDetail t = theirs.getLevelsOfDetail().get(i);
Log.i(TAG," our LOD("+ i +"," + resolution + "," + scale + ")");
Log.i(TAG,"their LOD("+ t.getLevel() +"," + t.getResolution() + "," + t.getScale() + ")");
}
return theirs;
}
@Override
protected String getTileUrl(TileKey tileKey) {
String tileurl = baseurl.replace("{level}",String.valueOf(tileKey.getLevel())).replace("{col}",String.valueOf(tileKey.getColumn())).replace("{row}",String.valueOf(tileKey.getRow()));
Log.d(TAG,"Url = " +tileurl);
return tileurl;
}
@Override
public String getId() {
return super.getId();
}
@Override
public void setId(String id) {
super.setId(id);
}
}