Adding an Authorization header in getTileUrl for M

2019-08-07 18:53发布

I would like to access some Custom Map Tiles when creating a TileOverlay for Google Maps API.

So this is my current code:

TileProvider tileProvider = new UrlTileProvider(256, 256) {
        @Override
        public URL getTileUrl(int x, int y, int z) {

            String url = String.format("https://api.mycustommaps.com/v1/%d/%d/%d.jpg", z, x, y);

            if (!checkTileExists(x, y, z)) {
                return null;
            }

            try {
                URL tileUrl = new URL(url);
                tileUrl.openConnection().addRequestProperty("Authorization", LOGIN_TOKEN);
                return tileUrl;
            } catch (MalformedURLException e) {
                e.printStackTrance();
            } catch (IOException e) {
                e.printStackTrance();
            }
            return null;
        }
    };

Since the connection returns 401 Anauthorized, I can't access the tiles. How could I pass Authorization header to let the url know I am authorized to access those tiles?

1条回答
倾城 Initia
2楼-- · 2019-08-07 19:32

you have to implement the "TileProvider" interface, not URLTileProvider (because you have to retrieve the tile on your own, an URL is not enough. https://developers.google.com/android/reference/com/google/android/gms/maps/model/TileProvider as you can see, there is a note to keep attention:

Calls to methods in this interface might be made from multiple threads so implementations of this interface must be threadsafe.

and you have to implement a single method:

abstract Tile getTile(int x, int y, int zoom)

It is now your work download the tile, I've done it for local files, so I'm just writing here some code that might need some more refinement and testing:

@Override
public Tile getTile(int x, int y, int zoom) {
  String url = String.format("https://api.mycustommaps.com/v1/%d/%d/%d.jpg", z, x, y);

  if (!checkTileExists(x, y, z)) {
     return null;
  }

  try {
    URL tileUrl = new URL(url);
    //Download the PNG as byte[], I suggest using OkHTTP library or see next code! 
    final byte[] data = downloadData(tileUrl);
    final int height = tileheight;
    final int width =  tilewidth;
    if (data != null) {
        if (BuildConfig.DEBUG)Log.d(TAG, "Cache hit for tile " + key);
           return new Tile(width, height, data);
    }
    //In this case error, maybe return a placeholder tile or TileProvider.NO_TILE

  } catch (MalformedURLException e) {
     e.printStackTrance();
  } catch (IOException e) {
       e.printStackTrance();
  }
}

to download:

byte[] downloadData(URL url){ 
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
try {
  tileUrl.openConnection().addRequestProperty("Authorization", LOGIN_TOKEN);
  is = url.openStream();
  byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
  int n;

  while ( (n = is.read(byteChunk)) > 0 ) {
    baos.write(byteChunk, 0, n);
  }
}
catch (IOException e) {
  System.err.printf ("Failed while reading bytes from %s: %s", url.toExternalForm(), e.getMessage());
  e.printStackTrace ();
  // Perform any other exception handling that's appropriate.
}
finally {
  if (is != null) { is.close(); }
}
return baos.toByteArray():
查看更多
登录 后发表回答