Fix: some old code is mixed.
MODIFY
src/android/plugin/google/maps/PluginMarker.java
src/android/plugin/google/maps/PluginMarker.java
package plugin.google.maps;
import android.content.res.AssetManager;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.Typeface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
@@ -44,9 +49,10 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
BOUNCE
}
- private ArrayList<AsyncTask> iconLoadingTasks = new ArrayList<AsyncTask>();
- private ArrayList<Bitmap> icons = new ArrayList<Bitmap>();
- private HashMap<String, Integer> iconCacheKeys = new HashMap<String, Integer>();
+ protected ArrayList<AsyncTask> iconLoadingTasks = new ArrayList<AsyncTask>();
+ protected ArrayList<Bitmap> icons = new ArrayList<Bitmap>();
+ protected HashMap<String, Integer> iconCacheKeys = new HashMap<String, Integer>();
+ private static Paint paint = new Paint();
@Override
public void initialize(CordovaInterface cordova, final CordovaWebView webView) {
@@ -60,9 +66,6 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
- if (objects == null) {
- return;
- }
Set<String> keySet = objects.keySet();
String[] objectIdArray = keySet.toArray(new String[keySet.size()]);
@@ -72,8 +75,7 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
!objectId.startsWith("marker_property_") &&
!objectId.startsWith("marker_icon_")) {
Marker marker = (Marker) objects.remove(objectId);
- marker.setIcon(null);
- marker.remove();
+ _removeMarker(marker);
marker = null;
} else {
Object object = objects.remove(objectId);
@@ -83,7 +85,6 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
}
objects.clear();
- objects = null;
}
});
@@ -134,9 +135,6 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
- if (objects == null) {
- return;
- }
Set<String> keySet = objects.keySet();
String[] objectIdArray = keySet.toArray(new String[keySet.size()]);
@@ -147,6 +145,7 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
!objectId.startsWith("marker_icon_")) {
Marker marker = (Marker) objects.remove(objectId);
marker.setIcon(null);
+ marker.setTag(null);
marker.remove();
marker = null;
} else {
@@ -226,11 +225,18 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
} else {
properties.put("noCache", false);
}
+ if (opts.has("useHtmlInfoWnd")) {
+ properties.put("useHtmlInfoWnd", opts.getBoolean("useHtmlInfoWnd"));
+ } else {
+ properties.put("useHtmlInfoWnd", false);
+ }
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
final Marker marker = map.addMarker(markerOptions);
+ final String markerId = "marker_" + marker.getId();
+ marker.setTag(markerId);
marker.hideInfoWindow();
cordova.getThreadPool().execute(new Runnable() {
@@ -239,15 +245,13 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
try {
// Store the marker
- String id = "marker_" + marker.getId();
- self.objects.put(id, marker);
+ self.objects.put(markerId, marker);
- self.objects.put("marker_property_" + marker.getId(), properties);
+ self.objects.put("marker_property_" + marker.getTag(), properties);
// Prepare the result
final JSONObject result = new JSONObject();
- result.put("hashCode", marker.hashCode());
- result.put("id", id);
+ result.put("id", markerId);
// Load icon
@@ -259,6 +263,13 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
Object value = opts.get("icon");
if (JSONObject.class.isInstance(value)) {
JSONObject iconProperty = (JSONObject) value;
+ if (iconProperty.has("label")) {
+ JSONObject label = iconProperty.getJSONObject("label");
+ if (label != null && label.get("color") instanceof JSONArray) {
+ label.put("color", PluginUtil.parsePluginColor(label.getJSONArray("color")));
+ iconProperty.put("label", label);
+ }
+ }
bundle = PluginUtil.Json2Bundle(iconProperty);
// The `anchor` of the `icon` property
@@ -271,6 +282,11 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
anchorPoints[i] = points.getDouble(i);
}
bundle.putDoubleArray("anchor", anchorPoints);
+ } else if (value instanceof JSONObject && ((JSONObject) value).has("x") && ((JSONObject) value).has("y")) {
+ double[] anchorPoints = new double[2];
+ anchorPoints[0] = ((JSONObject) value).getDouble("x");
+ anchorPoints[1] = ((JSONObject) value).getDouble("y");
+ bundle.putDoubleArray("anchor", anchorPoints);
}
}
@@ -284,8 +300,14 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
anchorPoints[i] = points.getDouble(i);
}
bundle.putDoubleArray("infoWindowAnchor", anchorPoints);
+ } else if (value instanceof JSONObject && ((JSONObject) value).has("x") && ((JSONObject) value).has("y")) {
+ double[] anchorPoints = new double[2];
+ anchorPoints[0] = ((JSONObject) value).getDouble("x");
+ anchorPoints[1] = ((JSONObject) value).getDouble("y");
+ bundle.putDoubleArray("infoWindowAnchor", anchorPoints);
}
}
+
} else if (JSONArray.class.isInstance(value)) {
float[] hsv = new float[3];
JSONArray arrayRGBA = (JSONArray) value;
@@ -649,7 +671,7 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
this.sendNoResult(callbackContext);
return;
}
- String propertyId = "marker_property_" + marker.getId();
+ String propertyId = "marker_property_" + marker.getTag();
JSONObject properties = null;
if (self.objects.containsKey(propertyId)) {
properties = (JSONObject)self.objects.get(propertyId);
@@ -674,7 +696,7 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
this.sendNoResult(callbackContext);
return;
}
- String propertyId = "marker_property_" + marker.getId();
+ String propertyId = "marker_property_" + marker.getTag();
JSONObject properties = null;
if (self.objects.containsKey(propertyId)) {
properties = (JSONObject)self.objects.get(propertyId);
@@ -692,19 +714,9 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
* @throws JSONException
*/
public void setTitle(final JSONArray args, final CallbackContext callbackContext) throws JSONException {
- final String title = args.getString(1);
- final String id = args.getString(0);
-
- cordova.getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Marker marker = getMarker(id);
- if (marker != null) {
- marker.setTitle(title);
- }
- sendNoResult(callbackContext);
- }
- });
+ String title = args.getString(1);
+ String id = args.getString(0);
+ this.setString("setTitle", id, title, callbackContext);
}
/**
@@ -760,24 +772,43 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
}
*/
- String propertyId = "marker_property_" + id;
+ String propertyId = "marker_property_" + marker.getTag();
objects.remove(propertyId);
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
- marker.remove();
+
if (objects != null) {
objects.remove(id);
}
- String iconCacheKey = "marker_icon_" + marker.getId();
+ _removeMarker(marker);
+
+ sendNoResult(callbackContext);
+ }
+ });
+ }
+ protected void _removeMarker(Marker marker) {
+ if (marker == null || marker.getTag() == null) {
+ return;
+ }
+ //---------------------------------------------
+ // Removes marker safely
+ // (prevent the `un-managed object exception`)
+ //---------------------------------------------
+ String iconCacheKey = "marker_icon_" + marker.getTag();
+ marker.setTag(null);
+ marker.remove();
+
+ //---------------------------------------------------------------------------------
+ // If no marker uses the icon image used be specified this marker, release it
+ //---------------------------------------------------------------------------------
if (objects.containsKey(iconCacheKey)) {
String cacheKey = (String) objects.remove(iconCacheKey);
if (iconCacheKeys.containsKey(cacheKey)) {
int count = iconCacheKeys.get(cacheKey);
count--;
if (count < 1) {
- // gc
AsyncLoadImage.removeBitmapFromMemCahce(cacheKey);
iconCacheKeys.remove(cacheKey);
} else {
@@ -786,10 +817,6 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
}
objects.remove(iconCacheKey);
}
-
- sendNoResult(callbackContext);
- }
- });
}
/**
@@ -868,6 +895,11 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
anchorPoints[i] = points.getDouble(i);
}
bundle.putDoubleArray("anchor", anchorPoints);
+ } else if (value instanceof JSONObject && ((JSONObject) value).has("x") && ((JSONObject) value).has("y")) {
+ double[] anchorPoints = new double[2];
+ anchorPoints[0] = ((JSONObject) value).getDouble("x");
+ anchorPoints[1] = ((JSONObject) value).getDouble("y");
+ bundle.putDoubleArray("anchor", anchorPoints);
}
}
} else if (JSONArray.class.isInstance(value)) {
@@ -898,7 +930,7 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
}
}
- private void setIcon_(final Marker marker, final Bundle iconProperty, final PluginAsyncInterface callback) {
+ protected void setIcon_(final Marker marker, final Bundle iconProperty, final PluginAsyncInterface callback) {
boolean noCaching = false;
if (iconProperty.containsKey("noCache")) {
noCaching = iconProperty.getBoolean("noCache");
@@ -912,255 +944,92 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
}
});
callback.onPostExecute(marker);
- }
-
- String iconUrl = iconProperty.getString("url");
- if (iconUrl == null) {
- callback.onPostExecute(marker);
return;
}
- if (!iconUrl.contains("://") &&
- !iconUrl.startsWith("/") &&
- !iconUrl.startsWith("www/") &&
- !iconUrl.startsWith("data:image") &&
- !iconUrl.startsWith("./") &&
- !iconUrl.startsWith("../")) {
- iconUrl = "./" + iconUrl;
- }
- if (iconUrl.startsWith("./") || iconUrl.startsWith("../")) {
- iconUrl = iconUrl.replace("././", "./");
- String currentPage = CURRENT_PAGE_URL;
- currentPage = currentPage.replaceAll("[^\\/]*$", "");
- iconUrl = currentPage + "/" + iconUrl;
- }
-
+ String iconUrl = iconProperty.getString("url");
if (iconUrl == null) {
callback.onPostExecute(marker);
return;
}
- iconProperty.putString("url", iconUrl);
-
- if (iconUrl.indexOf("http") != 0) {
- //----------------------------------
- // Load icon from local file
- //----------------------------------
- AsyncTask<Void, Void, Bitmap> task = new AsyncTask<Void, Void, Bitmap>() {
-
- @Override
- protected Bitmap doInBackground(Void... params) {
- String iconUrl = iconProperty.getString("url");
- if (iconUrl == null) {
- return null;
- }
-
- Bitmap image = null;
- if (iconUrl.indexOf("cdvfile://") == 0) {
- CordovaResourceApi resourceApi = webView.getResourceApi();
- iconUrl = PluginUtil.getAbsolutePathFromCDVFilePath(resourceApi, iconUrl);
- }
- if (iconUrl == null) {
- return null;
- }
-
- if (iconUrl.indexOf("data:image/") == 0 && iconUrl.contains(";base64,")) {
- String[] tmp = iconUrl.split(",");
- image = PluginUtil.getBitmapFromBase64encodedImage(tmp[1]);
- } else if (iconUrl.indexOf("file://") == 0 &&
- !iconUrl.contains("file:///android_asset/")) {
- iconUrl = iconUrl.replace("file://", "");
- File tmp = new File(iconUrl);
- if (tmp.exists()) {
- image = BitmapFactory.decodeFile(iconUrl);
- } else {
- //if (PluginMarker.this.mapCtrl.mPluginLayout.isDebug) {
- Log.w("GoogleMaps", "icon is not found (" + iconUrl + ")");
- //}
- }
- } else {
- //Log.d(TAG, "iconUrl = " + iconUrl);
- if (iconUrl.indexOf("file:///android_asset/") == 0) {
- iconUrl = iconUrl.replace("file:///android_asset/", "");
- }
- //Log.d(TAG, "iconUrl = " + iconUrl);
- if (iconUrl.contains("./")) {
- try {
- boolean isAbsolutePath = iconUrl.startsWith("/");
- File relativePath = new File(iconUrl);
- iconUrl = relativePath.getCanonicalPath();
- //Log.d(TAG, "iconUrl = " + iconUrl);
- if (!isAbsolutePath) {
- iconUrl = iconUrl.substring(1);
- }
- //Log.d(TAG, "iconUrl = " + iconUrl);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- AssetManager assetManager = PluginMarker.this.cordova.getActivity().getAssets();
- InputStream inputStream;
- try {
- inputStream = assetManager.open(iconUrl);
- image = BitmapFactory.decodeStream(inputStream);
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- }
- if (image == null) {
- return null;
- }
- icons.add(image);
-
- Boolean isResized = false;
+ int width = -1;
+ int height = -1;
if (iconProperty.containsKey("size")) {
- Object size = iconProperty.get("size");
-
- if (Bundle.class.isInstance(size)) {
-
- Bundle sizeInfo = (Bundle)size;
- int width = sizeInfo.getInt("width", 0);
- int height = sizeInfo.getInt("height", 0);
- if (width > 0 && height > 0) {
- isResized = true;
- width = (int)Math.round(width * PluginMarker.this.density);
- height = (int)Math.round(height * PluginMarker.this.density);
- image = PluginUtil.resizeBitmap(image, width, height);
- }
- }
- }
-
- if (!isResized) {
- image = PluginUtil.scaleBitmapForDevice(image);
+ Bundle sizeInfo = (Bundle) iconProperty.get("size");
+ width = sizeInfo.getInt("width", width);
+ height = sizeInfo.getInt("height", height);
}
- icons.add(image);
- return image;
- }
+ final AsyncLoadImage.AsyncLoadImageOptions options = new AsyncLoadImage.AsyncLoadImageOptions();
+ options.url = iconUrl;
+ options.width = width;
+ options.height = height;
+ options.noCaching = noCaching;
+ AsyncLoadImage task = new AsyncLoadImage(cordova, webView, options, new AsyncLoadImageInterface() {
@Override
- protected void onPostExecute(Bitmap image) {
- if (image == null) {
+ public void onPostExecute(AsyncLoadImage.AsyncLoadImageResult result) {
+ if (result == null || result.image == null) {
callback.onPostExecute(marker);
return;
}
- if (image.isRecycled()) {
+ if (result.image.isRecycled()) {
//Maybe the task was canceled by map.clean()?
callback.onError("Can not get image for marker. Maybe the task was canceled by map.clean()?");
return;
}
- try {
- BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(image);
- if (bitmapDescriptor == null) {
- callback.onPostExecute(marker);
- return;
- }
- marker.setIcon(bitmapDescriptor);
-
- // Save the information for the anchor property
- Bundle imageSize = new Bundle();
- imageSize.putInt("width", image.getWidth());
- imageSize.putInt("height", image.getHeight());
- self.objects.put("imageSize", imageSize);
-
-
- // The `anchor` of the `icon` property
- if (iconProperty.containsKey("anchor")) {
- double[] anchor = iconProperty.getDoubleArray("anchor");
- if (anchor.length == 2) {
- _setIconAnchor(marker, anchor[0], anchor[1], imageSize.getInt("width"), imageSize.getInt("height"));
- }
- }
-
+ icons.add(result.image);
- // The `anchor` property for the infoWindow
- if (iconProperty.containsKey("infoWindowAnchor")) {
- double[] anchor = iconProperty.getDoubleArray("infoWindowAnchor");
- if (anchor.length == 2) {
- _setInfoWindowAnchor(marker, anchor[0], anchor[1], imageSize.getInt("width"), imageSize.getInt("height"));
- }
- }
-
- callback.onPostExecute(marker);
-
- } catch (Exception e) {
- Log.e(TAG,"PluginMarker: Warning - marker method called when marker has been disposed, wait for addMarker callback before calling more methods on the marker (setIcon etc).");
- //e.printStackTrace();
- try {
- marker.remove();
- } catch (Exception ignore) {
- ignore = null;
- }
- callback.onError(e.getMessage() + "");
- }
- }
- };
- task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- iconLoadingTasks.add(task);
-
-
- return;
+ //-------------------------------------------------------
+ // Counts up the markers that use the same icon image.
+ //-------------------------------------------------------
+ if (result.cacheHit) {
+ String hitCountKey = "marker_icon_" + marker.getTag();
+ objects.put(hitCountKey, result.cacheKey);
+ if (!iconCacheKeys.containsKey(result.cacheKey)) {
+ iconCacheKeys.put(result.cacheKey, 1);
+ } else {
+ int count = iconCacheKeys.get(result.cacheKey);
+ iconCacheKeys.put(result.cacheKey, count + 1);
}
-
- if (iconUrl.indexOf("http") == 0) {
- //----------------------------------
- // Load icon from on the internet
- //----------------------------------
- int width = -1;
- int height = -1;
- if (iconProperty.containsKey("size")) {
-
- Bundle sizeInfo = (Bundle) iconProperty.get("size");
- width = sizeInfo.getInt("width", width);
- height = sizeInfo.getInt("height", height);
}
- String cacheKey = AsyncLoadImage.getCacheKey(iconUrl, width, height);
- objects.put("marker_icon_" + marker.getId(), cacheKey);
- if (!iconCacheKeys.containsKey(cacheKey)) {
- iconCacheKeys.put(cacheKey, 1);
- } else {
- int count = iconCacheKeys.get(cacheKey);
- iconCacheKeys.put(cacheKey, count + 1);
+ //------------------------
+ // Draw label on icon
+ //------------------------
+ if (iconProperty.containsKey("label")) {
+ result.image = drawLabel(result.image, iconProperty.getBundle("label"));
}
-
- AsyncLoadImage task = new AsyncLoadImage("Mozilla", width, height, noCaching, new AsyncLoadImageInterface() {
-
- @Override
- public void onPostExecute(Bitmap image) {
-
- if (image == null) {
+ BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(result.image);
+ if (bitmapDescriptor == null || marker.getTag() == null) {
callback.onPostExecute(marker);
return;
}
- if (image.isRecycled()) {
- //Maybe the task was canceled by map.clean()?
- callback.onError("Can not get image for marker. Maybe the task was canceled by map.clean()?");
- return;
- }
- try {
- icons.add(image);
- BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(image);
+ //------------------------
+ // Sets image as icon
+ //------------------------
marker.setIcon(bitmapDescriptor);
+ //---------------------------------------------
// Save the information for the anchor property
+ //---------------------------------------------
Bundle imageSize = new Bundle();
- imageSize.putInt("width", image.getWidth());
- imageSize.putInt("height", image.getHeight());
+ imageSize.putInt("width", result.image.getWidth());
+ imageSize.putInt("height", result.image.getHeight());
self.objects.put("imageSize", imageSize);
// The `anchor` of the `icon` property
if (iconProperty.containsKey("anchor")) {
double[] anchor = iconProperty.getDoubleArray("anchor");
- if (anchor.length == 2) {
+ if (anchor != null && anchor.length == 2) {
_setIconAnchor(marker, anchor[0], anchor[1], imageSize.getInt("width"), imageSize.getInt("height"));
}
}
+
// The `anchor` property for the infoWindow
if (iconProperty.containsKey("infoWindowAnchor")) {
double[] anchor = iconProperty.getDoubleArray("infoWindowAnchor");
@@ -1169,23 +1038,12 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
}
}
- image.recycle();
callback.onPostExecute(marker);
- } catch (Exception e) {
- //e.printStackTrace();
- try {
- marker.remove();
- } catch (Exception ignore) {
- ignore = null;
- }
- callback.onError(e.getMessage() + "");
- }
}
});
- task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, iconUrl);
+ task.execute();
iconLoadingTasks.add(task);
}
- }
private void _setIconAnchor(final Marker marker, double anchorX, double anchorY, final int imageWidth, final int imageHeight) {
// The `anchor` of the `icon` property
@@ -1213,4 +1071,58 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
}
});
}
+
+ protected Bitmap drawLabel(Bitmap image, Bundle labelOptions) {
+ String text = labelOptions.getString("text");
+ if (text == null || text.length() == 0) {
+ return image;
+ }
+ Bitmap newIcon = Bitmap.createBitmap(image);
+ Canvas canvas = new Canvas(newIcon);
+ image.recycle();
+ image = null;
+
+ int fontSize = 10;
+ if (labelOptions.containsKey("fontSize")) {
+ fontSize = labelOptions.getInt("fontSize");
+ }
+ paint.setTextSize(fontSize * density);
+
+ int color = Color.BLACK;
+ if (labelOptions.containsKey("color")) {
+ color = labelOptions.getInt("color");
+ }
+ boolean bold = false;
+ if (labelOptions.containsKey("bold")) {
+ bold = labelOptions.getBoolean("bold");
+ }
+ paint.setFakeBoldText(bold);
+ boolean italic = false;
+ if (labelOptions.containsKey("italic")) {
+ italic = labelOptions.getBoolean("italic");
+ }
+ if (italic && bold) {
+ paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD_ITALIC));
+ } else if(italic) {
+ paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC));
+ } else if(bold) {
+ paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
+ } else {
+ paint.setTypeface(Typeface.DEFAULT);
+ }
+ paint.setColor(color);
+
+
+ Rect rect = new Rect();
+ canvas.getClipBounds(rect);
+ int cHeight = rect.height();
+ int cWidth = rect.width();
+ paint.setTextAlign(Paint.Align.LEFT);
+ paint.getTextBounds(text, 0, text.length(), rect);
+ float x = cWidth / 2f - rect.width() / 2f - rect.left;
+ float y = cHeight / 2f + rect.height() / 2f - rect.bottom;
+ canvas.drawText(text, x, y, paint);
+ return newIcon;
+ }
+
}

Fix: some old code is mixed.