Add: the debug option for map.addTileLayer()
Revert: patch
MODIFY
plugin.xml
plugin.xml
<?xml version='1.0' encoding='utf-8'?>
-<plugin id="cordova-plugin-googlemaps" version="2.0.0-beta2-20170720-2325" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
+<plugin id="cordova-plugin-googlemaps" version="2.0.0-beta2-20170721-1617" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
<name>cordova-plugin-googlemaps</name>
<js-module name="BaseClass" src="www/BaseClass.js">
<runs />

MODIFY
src/android/plugin/google/maps/PluginTileOverlay.java
src/android/plugin/google/maps/PluginTileOverlay.java
@@ -41,7 +41,13 @@ public class PluginTileOverlay extends MyPlugin implements MyPluginInterface {
if (opts.has("opacity")) {
options.transparency((float)(1 - opts.getDouble("opacity")));
}
+
+ boolean isDebug = false;
+ if (opts.has("debug")) {
+ isDebug = opts.getBoolean("debug");
+ }
final String id = opts.getString("_id");
+ final boolean _isDebug = isDebug;
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
@@ -58,7 +64,7 @@ public class PluginTileOverlay extends MyPlugin implements MyPluginInterface {
String currentPageUrl = webView.getUrl();
AssetManager assetManager = cordova.getActivity().getAssets();
- final PluginTileProvider tileProvider = new PluginTileProvider(pluginMap.mapId, id, webView, assetManager, currentPageUrl, userAgent, tileSize);
+ final PluginTileProvider tileProvider = new PluginTileProvider(pluginMap.mapId, id, webView, assetManager, currentPageUrl, userAgent, tileSize, _isDebug);
tileProvider.setOnCacheClear(new PluginTileProvider.OnCacheClear() {
@Override
public void onCacheClear(int hashCode) {
@@ -94,10 +100,11 @@ public class PluginTileOverlay extends MyPlugin implements MyPluginInterface {
@SuppressWarnings("unused")
public void onGetTileUrlFromJS(final JSONArray args, final CallbackContext callbackContext) throws JSONException {
String id = args.getString(0);
- String tileUrl = args.getString(1);
+ String urlKey = args.getString(1);
+ String tileUrl = args.getString(2);
String pluginId = "tileprovider_" + id;
if (objects.containsKey(pluginId)) {
- ((PluginTileProvider)(this.objects.get(pluginId))).onGetTileUrlFromJS(tileUrl);
+ ((PluginTileProvider)(this.objects.get(pluginId))).onGetTileUrlFromJS(urlKey, tileUrl);
}
callbackContext.success();
}
@@ -149,6 +156,9 @@ public class PluginTileOverlay extends MyPlugin implements MyPluginInterface {
try {
String id = args.getString(0);
id = id.replace("tileoverlay_", "tileprovider_");
+ if (objects.containsKey(id)) {
+ ((PluginTileProvider)(objects.get(id))).remove();
+ }
self.objects.put(id, null);
self.objects.remove(id);
sendNoResult(callbackContext);

MODIFY
src/android/plugin/google/maps/PluginTileProvider.java
src/android/plugin/google/maps/PluginTileProvider.java
@@ -6,10 +6,14 @@ import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Looper;
+import android.text.Layout;
+import android.text.StaticLayout;
+import android.text.TextPaint;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
@@ -27,11 +31,17 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.Locale;
public class PluginTileProvider implements TileProvider {
private int tileSize = 256;
private Paint tilePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+ private Paint debugPaint = null;
+ private TextPaint debugTextPaint = null;
private String userAgent = null;
private static BitmapCache tileCache = null;
private OnCacheClear listener = null;
@@ -39,12 +49,15 @@ public class PluginTileProvider implements TileProvider {
private AssetManager assetManager;
private CordovaWebView webView;
private String mapId, pluginId;
- private String tileUrl;
+ private final HashMap<String, String> tileUrlMap = new HashMap<String, String>();
+ private boolean isDebug = false;
private Handler handler;
- private Object semaphore = new Object();
+ private final Object semaphore = new Object();
+ private Bitmap emptyBitmap = null;
+ private final HashSet<String> cacheKeys = new HashSet<String>();
@SuppressLint({"NewApi", "JavascriptInterface"})
- public PluginTileProvider(String mapId, String pluginId, CordovaWebView webView, AssetManager assetManager, String webPageUrl, String userAgent, int tileSize) {
+ public PluginTileProvider(String mapId, String pluginId, CordovaWebView webView, AssetManager assetManager, String webPageUrl, String userAgent, int tileSize, boolean isDebug) {
this.tileSize = tileSize;
//this.tilePaint.setAlpha((int) (opacity * 255));
this.userAgent = userAgent == null ? "Mozilla" : userAgent;
@@ -64,6 +77,20 @@ public class PluginTileProvider implements TileProvider {
tileCache = new BitmapCache(cacheSize);
+ this.isDebug = isDebug;
+ if (isDebug) {
+ debugPaint = new Paint();
+ debugPaint.setTextSize(20);
+ debugPaint.setColor(Color.RED);
+ debugPaint.setStrokeWidth(1);
+ debugPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+
+ debugTextPaint = new TextPaint();
+ debugTextPaint.setTextSize(20);
+ debugTextPaint.setColor(Color.RED);
+ debugTextPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+ }
+
handler = new Handler(Looper.getMainLooper());
}
@@ -72,13 +99,32 @@ public class PluginTileProvider implements TileProvider {
public void onCacheClear(int hashCode);
}
- public void onGetTileUrlFromJS(String tileUrl) {
- this.tileUrl = tileUrl;
+
+ public void onGetTileUrlFromJS(String urlKey, String tileUrl) {
+ synchronized (tileUrlMap) {
+ tileUrlMap.put(urlKey, tileUrl);
+ }
synchronized (semaphore) {
semaphore.notify();
}
}
+ public void remove() {
+ synchronized (cacheKeys) {
+ Iterator<String> iterator = cacheKeys.iterator();
+ String cacheKey;
+ Bitmap image;
+ while(iterator.hasNext()) {
+ cacheKey = iterator.next();
+ image = tileCache.remove(cacheKey);
+ if (image != null && !image.isRecycled()) {
+ image.recycle();
+ image = null;
+ }
+ }
+ }
+ tileCache.evictAll();
+ }
public void setOnCacheClear(OnCacheClear listener) {
this.listener = listener;
}
@@ -87,9 +133,11 @@ public class PluginTileProvider implements TileProvider {
public Tile getTile(int x, int y, int zoom) {
String urlStr = null;
+ String originalUrlStr = null;
+ final String urlKey = String.format(Locale.US, "%s-%s-%d-%d-%d", mapId, pluginId, x, y, zoom);
synchronized (semaphore) {
- final String js = String.format(Locale.ENGLISH, "javascript:cordova.fireDocumentEvent('%s-%s-tileoverlay', {x: %d, y: %d, zoom: %d})",
- mapId, pluginId, x, y, zoom);
+ final String js = String.format(Locale.ENGLISH, "javascript:cordova.fireDocumentEvent('%s-%s-tileoverlay', {key: \"%s\", x: %d, y: %d, zoom: %d})",
+ mapId, pluginId, urlKey, x, y, zoom);
handler.post(new Runnable() {
@Override
@@ -98,18 +146,33 @@ public class PluginTileProvider implements TileProvider {
}
});
try {
- semaphore.wait();
+ semaphore.wait(10 * 1000); // Maximum wait 10sec
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
- urlStr = tileUrl;
}
- if ("(null)".equals(urlStr)) {
- return null;
+ synchronized (tileUrlMap) {
+ urlStr = tileUrlMap.remove(urlKey);
}
+ originalUrlStr = urlStr;
Tile tile = null;
+ if (urlStr == null || "(null)".equals(urlStr)) {
+ if (isDebug) {
+ if (emptyBitmap == null) {
+ emptyBitmap = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888);
+ }
+ Bitmap dummyBitmap = emptyBitmap.copy(Config.ARGB_8888, true);
+ drawDebugInfo(dummyBitmap, x, y, zoom, originalUrlStr);
+ tile = new Tile(tileSize, tileSize, bitmapToByteArray(dummyBitmap));
+ dummyBitmap.recycle();
+ return tile;
+ } else {
+ return null;
+ }
+ }
+
try {
InputStream inputStream = null;
if (urlStr.startsWith("http://") || urlStr.startsWith("https://")) {
@@ -121,8 +184,17 @@ public class PluginTileProvider implements TileProvider {
URL url = new URL(urlStr);
String cacheKey = url.hashCode() + "";
Bitmap cachedImage = tileCache.get(cacheKey);
- if (cachedImage != null) {
- return new Tile(tileSize, tileSize, bitmapToByteArray(cachedImage));
+ if (cachedImage != null && !cachedImage.isRecycled()) {
+ if (isDebug) {
+ Bitmap copyImage = cachedImage.copy(Config.ARGB_8888, true);
+ drawDebugInfo(copyImage, x, y, zoom, originalUrlStr);
+ tile = new Tile(tileSize, tileSize, bitmapToByteArray(copyImage));
+ copyImage.recycle();
+ } else {
+ tile = new Tile(tileSize, tileSize, bitmapToByteArray(cachedImage));
+ }
+ //cachedImage.recycle(); // Don't recycle it. Need to keep the bitmap instance
+ return tile;
}
HttpURLConnection http = null;
@@ -164,15 +236,24 @@ public class PluginTileProvider implements TileProvider {
inputStream = http.getInputStream();
Bitmap image = BitmapFactory.decodeStream(inputStream);
+ if (image != null) {
if (image.getWidth() != tileSize || image.getHeight() != tileSize) {
Bitmap tileImage = this.resizeForTile(image);
+ tileCache.put(cacheKey, tileImage.copy(Config.ARGB_8888, true));
+ if (isDebug) {
+ drawDebugInfo(tileImage, x, y, zoom, originalUrlStr);
+ }
tile = new Tile(tileSize, tileSize, bitmapToByteArray(tileImage));
- tileCache.put(cacheKey, tileImage.copy(tileImage.getConfig(), false));
tileImage.recycle();
- image.recycle();
} else {
+ tileCache.put(cacheKey, image.copy(Config.ARGB_8888, true));
+
+ if (isDebug) {
+ drawDebugInfo(image, x, y, zoom, originalUrlStr);
+ }
tile = new Tile(tileSize, tileSize, bitmapToByteArray(image));
- tileCache.put(cacheKey, image.copy(image.getConfig(), false));
+ }
+ cacheKeys.add(cacheKey);
image.recycle();
}
http.disconnect();
@@ -198,8 +279,18 @@ public class PluginTileProvider implements TileProvider {
}
String cacheKey = new File(urlStr).hashCode() + "";
Bitmap cachedImage = tileCache.get(cacheKey);
- if (cachedImage != null) {
- return new Tile(tileSize, tileSize, bitmapToByteArray(cachedImage));
+ if (cachedImage != null && !cachedImage.isRecycled()) {
+ if (isDebug) {
+ Bitmap copyImage = cachedImage.copy(Config.ARGB_8888, true);
+ drawDebugInfo(copyImage, x, y, zoom, originalUrlStr);
+ cachedImage.recycle();
+ tile = new Tile(tileSize, tileSize, bitmapToByteArray(copyImage));
+ copyImage.recycle();
+ } else {
+ tile = new Tile(tileSize, tileSize, bitmapToByteArray(cachedImage));
+ }
+ //cachedImage.recycle(); // Don't recycle it. Need to keep the bitmap instance
+ return tile;
}
Bitmap image = null;
@@ -236,6 +327,9 @@ public class PluginTileProvider implements TileProvider {
try {
inputStream = assetManager.open(urlStr);
image = BitmapFactory.decodeStream(inputStream);
+ Bitmap tmpImage = image.copy(Config.ARGB_8888, true);
+ image.recycle();
+ image = tmpImage;
} catch (IOException e) {
//e.printStackTrace();
return null;
@@ -244,13 +338,21 @@ public class PluginTileProvider implements TileProvider {
if (image != null) {
if (image.getWidth() != tileSize || image.getHeight() != tileSize) {
Bitmap tileImage = this.resizeForTile(image);
+ tileCache.put(cacheKey, tileImage.copy(Config.ARGB_8888, true));
+ if (isDebug) {
+ drawDebugInfo(tileImage, x, y, zoom, originalUrlStr);
+ }
tile = new Tile(tileSize, tileSize, bitmapToByteArray(tileImage));
- tileCache.put(cacheKey, tileImage.copy(tileImage.getConfig(), false));
tileImage.recycle();
} else {
+ tileCache.put(cacheKey, image.copy(Config.ARGB_8888, true));
+ if (isDebug) {
+ drawDebugInfo(image, x, y, zoom, originalUrlStr);
+ }
tile = new Tile(tileSize, tileSize, bitmapToByteArray(image));
- tileCache.put(cacheKey, image);
}
+ image.recycle();
+ cacheKeys.add(cacheKey);
}
}
@@ -268,9 +370,21 @@ public class PluginTileProvider implements TileProvider {
return outputStream.toByteArray();
}
- //public void setOpacity(double opacity) {
- // this.tilePaint.setAlpha((int) (opacity * 255));
- //}
+ private void drawDebugInfo(Bitmap bitmap, int x, int y, int zoom, String url) {
+ Canvas canvas = new Canvas(bitmap);
+ canvas.drawLine(0, 0, tileSize, 0, debugPaint);
+ canvas.drawLine(0, 0, 0, tileSize, debugPaint);
+ canvas.drawText(String.format(Locale.US, "x = %d, y = %d, zoom = %d", x, y, zoom), 30, 30, debugPaint);
+ if (url != null) {
+ StaticLayout mTextLayout = new StaticLayout(url, debugTextPaint,
+ tileSize * 4 / 5, Layout.Alignment.ALIGN_NORMAL,
+ 1.0f, 0.0f, false);
+ canvas.save();
+ canvas.translate(30, 60);
+ mTextLayout.draw(canvas);
+ canvas.restore();
+ }
+ }
private Bitmap resizeForTile(Bitmap bitmap) {

MODIFY
src/ios/GoogleMaps/PluginTileOverlay.m
src/ios/GoogleMaps/PluginTileOverlay.m
///[options setObject:tileUrlFormat forKey:@"tileUrlFormat"];
[options setObject:[json objectForKey:@"tileSize"] forKey:@"tileSize"];
+ [options setObject:[json objectForKey:@"debug"] forKey:@"debug"];
layer = [[PluginTileProvider alloc] initWithOptions:options webView:webview];
/*
[self.executeQueue addOperationWithBlock:^{
NSString *_id = [command.arguments objectAtIndex:0];
- NSString *tileUrl = [command.arguments objectAtIndex:1];
+ NSString *urlKey = [command.arguments objectAtIndex:1];
+ NSString *tileUrl = [command.arguments objectAtIndex:2];
NSString *pluginId = [NSString stringWithFormat:@"tileoverlay_%@", _id];
GMSTileLayer *tileLayer = [self.objects objectForKey:pluginId];
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
if (tileLayer) {
PluginTileProvider *localLayer =(PluginTileProvider *)tileLayer;
- [localLayer onGetTileUrlFromJS:tileUrl];
+ [localLayer onGetTileUrlFromJS:urlKey tileUrl:tileUrl];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];

MODIFY
src/ios/GoogleMaps/PluginTileProvider.h
src/ios/GoogleMaps/PluginTileProvider.h
@property (nonatomic) NSString *tileUrlFormat;
@property (nonatomic) NSString *webPageUrl;
@property (nonatomic) UIView *webView;
-@property (nonatomic) CGFloat tile_size;
@property (nonatomic) NSString *mapId;
@property (nonatomic) NSString *pluginId;
-@property (nonatomic) NSString *_tileUrl;
+@property (nonatomic) NSMutableDictionary *tileUrlMap;
+@property (nonatomic) BOOL isDebug;
@property (nonatomic, strong) NSCache* imgCache;
@property (nonatomic) NSOperationQueue *executeQueue;
@property (nonatomic) dispatch_semaphore_t semaphore;
- (id)initWithOptions:(NSDictionary *) options webView:(UIView *)webView;
- (void)requestTileForX:(NSUInteger)x y:(NSUInteger)y zoom:(NSUInteger)zoom receiver:(id<GMSTileReceiver>)receiver;
-- (void)onGetTileUrlFromJS:(NSString *)tileUrl;
+- (void)onGetTileUrlFromJS:(NSString *)urlKey tileUrl:(NSString *)tileUrl;
- (void)downloadImageWithX:(NSUInteger)x y:(NSUInteger)y zoom:(NSUInteger)zoom url:(NSURL *)url receiver: (id<GMSTileReceiver>) receiver;
@end

MODIFY
src/ios/GoogleMaps/PluginTileProvider.m
src/ios/GoogleMaps/PluginTileProvider.m
@implementation PluginTileProvider
+CGRect tileRect;
+CGRect debugRect;
+UIFont *debugFont;
+NSDictionary *debugAttributes;
+
- (id)initWithOptions:(NSDictionary *) options webView:(UIView *)webView{
self = [super init];
self.webView = webView;
//self.tileUrlFormat = [options objectForKey:@"tileUrlFormat"];
self.webPageUrl = [options objectForKey:@"webPageUrl"];
if ([options objectForKey:@"tileSize"]) {
- self.tile_size = [[options objectForKey:@"tileSize"] floatValue];
+ self.tileSize = [[options objectForKey:@"tileSize"] floatValue];
} else {
- self.tile_size = 256.0f;
+ self.tileSize = 256.0f;
}
self.mapId = [options objectForKey:@"mapId"];
self.pluginId = [options objectForKey:@"pluginId"];
self.semaphore = dispatch_semaphore_create(0);
+ self.tileUrlMap = [NSMutableDictionary dictionary];
+
+
+ self.isDebug = NO;
+ if ([options objectForKey:@"debug"]) {
+ self.isDebug = YES;
+ tileRect = CGRectMake(0, 0 , self.tileSize, self.tileSize);
+ debugRect = CGRectMake(30, 30 , self.tileSize - 30, self.tileSize - 30);
+ debugFont = [UIFont systemFontOfSize:30.0f];
+ NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
+ style.lineBreakMode = NSLineBreakByWordWrapping;
+
+ debugAttributes = @{
+ NSForegroundColorAttributeName : [UIColor redColor],
+ NSFontAttributeName : debugFont,
+ NSParagraphStyleAttributeName : style
+ };
+ }
self.imgCache = [[NSCache alloc]init];
self.imgCache.totalCostLimit = 3 * 1024 * 1024 * 1024; // 3MB = Cache for image
}
}
-- (void)onGetTileUrlFromJS:(NSString *)tileUrl {
- self._tileUrl = tileUrl;
+- (void)onGetTileUrlFromJS:(NSString *)urlKey tileUrl:(NSString *)tileUrl {
+ @synchronized (self.tileUrlMap) {
+ [self.tileUrlMap setObject:tileUrl forKey:urlKey];
dispatch_semaphore_signal(self.semaphore);
}
+}
+
- (void)requestTileForX:(NSUInteger)x y:(NSUInteger)y zoom:(NSUInteger)zoom receiver:(id<GMSTileReceiver>)receiver {
- NSUInteger orginalZoom = zoom;
- if (floor(self.map.camera.zoom) < zoom) {
- zoom = zoom - 1; // Why does Google provides different zoom level?
- }
+ NSString *urlKey = [NSString stringWithFormat:@"%@-%@-%d-%d-%d",
+ self.mapId, self.pluginId, (int)x, (int)y, (int)zoom];
@synchronized (self.semaphore) {
// Execute the getTile() callback
NSString* jsString = [NSString
- stringWithFormat:@"javascript:cordova.fireDocumentEvent('%@-%@-tileoverlay', {x: %lu, y: %lu, zoom: %lu});",
- self.mapId, self.pluginId, (unsigned long)x, (unsigned long)y, (unsigned long)zoom];
+ stringWithFormat:@"javascript:cordova.fireDocumentEvent('%@-%@-tileoverlay', {key: \"%@\", x: %d, y: %d, zoom: %d});",
+ self.mapId, self.pluginId, urlKey, (int)x, (int)y, (int)zoom];
[self execJS:jsString];
}];
- dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
+ dispatch_semaphore_wait(self.semaphore, dispatch_time(DISPATCH_TIME_NOW, 10 * 1000 * 1000 * 1000)); // Maximum wait 10sec
}
- NSString *urlStr = self._tileUrl;
+ NSString *urlStr = nil;
+ @synchronized (self.tileUrlMap) {
+ urlStr = [self.tileUrlMap objectForKey:urlKey];
+ [self.tileUrlMap removeObjectForKey:urlKey];
+ } NSString *originalUrlStr = urlStr;
- if ([urlStr isEqualToString:@"(null)"]) {
+ if (urlStr == nil || [urlStr isEqualToString:@"(null)"]) {
//-------------------------
// No image tile
//-------------------------
- return [receiver receiveTileWithX:x y:y zoom:orginalZoom image:kGMSTileLayerNoTile];
+ if (self.isDebug) {
+ UIImage *image = [self drawDebugInfoWithImage:nil
+ x:x
+ y:y
+ zoom:zoom
+ url: originalUrlStr];
+ [receiver receiveTileWithX:x y:y zoom:zoom image:image];
+ } else {
+ [receiver receiveTileWithX:x y:y zoom:zoom image:kGMSTileLayerNoTile];
+ }
}
NSRange range = [urlStr rangeOfString:@"http"];
//-------------------------
// http:// or https://
//-------------------------
- [self downloadImageWithX:x y:y zoom:orginalZoom url:[NSURL URLWithString:urlStr] receiver:receiver];
+ [self downloadImageWithX:x y:y zoom:zoom url:[NSURL URLWithString:urlStr] receiver:receiver];
return;
}
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:urlStr]) {
- [receiver receiveTileWithX:x y:y zoom:orginalZoom image:kGMSTileLayerNoTile];
+ if (self.isDebug) {
+ UIImage *image = [self drawDebugInfoWithImage:nil
+ x:x
+ y:y
+ zoom:zoom
+ url: originalUrlStr];
+ [receiver receiveTileWithX:x y:y zoom:zoom image:image];
+ } else {
+ [receiver receiveTileWithX:x y:y zoom:zoom image:kGMSTileLayerNoTile];
+ }
return;
}
}
CGFloat screenScale = [[UIScreen mainScreen] scale];
UIImage *image = [UIImage imageWithData:data scale:screenScale];
if (image != nil &&
- (image.size.width != self.tile_size || image.size.height != self.tile_size)) {
+ (image.size.width != self.tileSize || image.size.height != self.tileSize)) {
- image = [image resize:self.tile_size height:self.tile_size];
+ image = [image resize:self.tileSize height:self.tileSize];
}
if (image != nil) {
- [receiver receiveTileWithX:x y:y zoom:orginalZoom image:image];
+ if (self.isDebug) {
+ image = [self drawDebugInfoWithImage:image
+ x:x
+ y:y
+ zoom:zoom
+ url: originalUrlStr];
+ [receiver receiveTileWithX:x y:y zoom:zoom image:image];
+ }
+ } else {
+ if (self.isDebug) {
+ UIImage *image = [self drawDebugInfoWithImage:nil
+ x:x
+ y:y
+ zoom:zoom
+ url: originalUrlStr];
+ [receiver receiveTileWithX:x y:y zoom:zoom image:image];
} else {
- [receiver receiveTileWithX:x y:y zoom:orginalZoom image:kGMSTileLayerNoTile];
+ [receiver receiveTileWithX:x y:y zoom:zoom image:kGMSTileLayerNoTile];
+ }
}
return;
}
+- (UIImage*)drawDebugInfoWithImage:(UIImage*)image x:(NSInteger)x y:(NSUInteger)y zoom:(NSUInteger)zoom url:(NSString *)url {
+
+ CGSize rectSize = CGSizeMake(self.tileSize, self.tileSize);
+ UIGraphicsBeginImageContextWithOptions(rectSize, NO, 0.0f);
+ CGContextRef context = UIGraphicsGetCurrentContext();
+
+ if (image != nil) {
+ [image drawInRect:tileRect];
+ //CGContextDrawImage(context, tileRect, image.CGImage);
+ }
+
+ CGContextSetAllowsAntialiasing(context, true);
+ CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
+ CGContextSetLineWidth(context, 2);
+ CGContextMoveToPoint(context, self.tileSize, 0);
+ CGContextAddLineToPoint(context, 0, 0);
+ CGContextAddLineToPoint(context, 0, self.tileSize);
+ CGContextStrokePath(context);
+
+ if (url) {
+ url = [NSString stringWithFormat:@"\n%@", url];
+ } else {
+ url = @"";
+ }
+
+ NSString *debugInfo = [NSString stringWithFormat:@"x = %d, y = %d, zoom = %d%@", (int)x, (int)y, (int)zoom, url];
+
+ [debugInfo drawInRect:debugRect withAttributes:debugAttributes];
+
+ UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ image = nil;
+ return newImage;
+}
- (void)downloadImageWithX:(NSUInteger)x y:(NSUInteger)y zoom:(NSUInteger)zoom url:(NSURL *)url receiver: (id<GMSTileReceiver>) receiver
{
NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:req];
if (cachedResponse != nil) {
UIImage *image = [[UIImage alloc] initWithData:cachedResponse.data];
+ if (self.isDebug) {
+ image = [self drawDebugInfoWithImage:image
+ x:x
+ y:y
+ zoom:zoom
+ url: url.absoluteString];
+ }
[receiver receiveTileWithX:x y:y zoom:zoom image:image];
return;
}
NSData *cache = [self.imgCache objectForKey:uniqueKey];
if (cache != nil) {
UIImage *image = [[UIImage alloc] initWithData:cache];
+ if (self.isDebug) {
+ image = [self drawDebugInfoWithImage:image
+ x:x
+ y:y
+ zoom:zoom
+ url: url.absoluteString];
+ }
[receiver receiveTileWithX:x y:y zoom:zoom image:image];
return;
}
if ( !error ) {
[self.imgCache setObject:data forKey:uniqueKey cost:data.length];
UIImage *image = [UIImage imageWithData:data];
+ if (self.isDebug) {
+ image = [self drawDebugInfoWithImage:image
+ x:x
+ y:y
+ zoom:zoom
+ url: url.absoluteString];
+ }
+ [receiver receiveTileWithX:x y:y zoom:zoom image:image];
+ } else {
+ if (self.isDebug) {
+ UIImage *image = [self drawDebugInfoWithImage:nil
+ x:x
+ y:y
+ zoom:zoom
+ url: url.absoluteString];
[receiver receiveTileWithX:x y:y zoom:zoom image:image];
} else {
[receiver receiveTileWithX:x y:y zoom:zoom image:kGMSTileLayerNoTile];
}
+ }
}];
[getTask resume];

MODIFY
www/Map.js
www/Map.js
@@ -771,6 +771,7 @@ Map.prototype.addTileOverlay = function(tilelayerOptions, callback) {
tilelayerOptions.zIndex = tilelayerOptions.zIndex || 0;
tilelayerOptions.tileSize = tilelayerOptions.tileSize || 256;
tilelayerOptions.opacity = tilelayerOptions.opacity || 1;
+ tilelayerOptions.debug = tilelayerOptions.debug === true;
tilelayerOptions.userAgent = tilelayerOptions.userAgent || navigator.userAgent;
var options = {
@@ -779,6 +780,7 @@ Map.prototype.addTileOverlay = function(tilelayerOptions, callback) {
tileSize: tilelayerOptions.tileSize,
opacity: tilelayerOptions.opacity,
userAgent: tilelayerOptions.userAgent,
+ debug: tilelayerOptions.debug,
_id : Math.floor(Math.random() * Date.now())
};
@@ -787,7 +789,7 @@ Map.prototype.addTileOverlay = function(tilelayerOptions, callback) {
if (!url || url === "(null)" || url === "undefined" || url === "null") {
url = "(null)";
}
- exec(null, self.errorHandler, self.id + "-tileoverlay", 'onGetTileUrlFromJS', [options._id, url]);
+ exec(null, self.errorHandler, self.id + "-tileoverlay", 'onGetTileUrlFromJS', [options._id, params.key, url]);
});
exec(function(result) {

Add: the debug option for map.addTileLayer()
Revert: #1565 patch