Java tutorial
package plugin.google.maps; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaInterface; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CordovaWebView; import org.apache.cordova.PluginEntry; import org.apache.cordova.PluginResult; import org.apache.cordova.ScrollEvent; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import plugin.http.request.HttpRequest; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Point; import android.graphics.Typeface; import android.location.Location; import android.location.LocationManager; import android.net.Uri; import android.os.Build; import android.os.Build.VERSION; import android.os.Bundle; import android.provider.Settings; import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebSettings.RenderPriority; import android.widget.AbsoluteLayout; import android.widget.FrameLayout; import android.widget.FrameLayout.LayoutParams; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks; import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.location.LocationClient; import com.google.android.gms.location.LocationListener; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter; import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener; import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener; import com.google.android.gms.maps.GoogleMap.OnMapClickListener; import com.google.android.gms.maps.GoogleMap.OnMapLoadedCallback; import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener; import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener; import com.google.android.gms.maps.GoogleMap.OnMarkerDragListener; import com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener; import com.google.android.gms.maps.GoogleMapOptions; import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.MapsInitializer; import com.google.android.gms.maps.Projection; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.CameraPosition.Builder; import com.google.android.gms.maps.model.Circle; import com.google.android.gms.maps.model.GroundOverlay; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.Polygon; import com.google.android.gms.maps.model.PolygonOptions; import com.google.android.gms.maps.model.Polyline; import com.google.android.gms.maps.model.VisibleRegion; @SuppressWarnings("deprecation") public class GoogleMaps extends CordovaPlugin implements View.OnClickListener, OnMarkerClickListener, OnInfoWindowClickListener, OnMapClickListener, OnMapLongClickListener, OnCameraChangeListener, OnMapLoadedCallback, OnMarkerDragListener, OnMyLocationButtonClickListener, InfoWindowAdapter { private final String TAG = "GoogleMapsPlugin"; private final HashMap<String, PluginEntry> plugins = new HashMap<String, PluginEntry>(); private float density; private enum EVENTS { onScrollChanged } private enum TEXT_STYLE_ALIGNMENTS { left, center, right } private JSONObject mapDivLayoutJSON = null; private MapView mapView = null; public GoogleMap map = null; private Activity activity; private LinearLayout windowLayer = null; private ViewGroup root; private final int CLOSE_LINK_ID = 0x7f999990; //random private final int LICENSE_LINK_ID = 0x7f99991; //random private final String PLUGIN_VERSION = "1.2.4"; private MyPluginLayout mPluginLayout = null; private LocationClient locationClient = null; private boolean isDebug = false; @SuppressLint("NewApi") @Override public void initialize(final CordovaInterface cordova, final CordovaWebView webView) { super.initialize(cordova, webView); activity = cordova.getActivity(); density = Resources.getSystem().getDisplayMetrics().density; root = (ViewGroup) webView.getParent(); // Is this app in debug mode? try { PackageManager manager = activity.getPackageManager(); ApplicationInfo appInfo = manager.getApplicationInfo(activity.getPackageName(), 0); isDebug = (appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == ApplicationInfo.FLAG_DEBUGGABLE; } catch (Exception e) { } Log.i("CordovaLog", "This app uses phonegap-googlemaps-plugin version " + PLUGIN_VERSION); if (isDebug) { cordova.getThreadPool().execute(new Runnable() { @Override public void run() { try { JSONArray params = new JSONArray(); params.put("get"); params.put("http://plugins.cordova.io/api/plugin.google.maps"); HttpRequest httpReq = new HttpRequest(); httpReq.initialize(cordova, null); httpReq.execute("execute", params, new CallbackContext("version_check", webView) { @Override public void sendPluginResult(PluginResult pluginResult) { if (pluginResult.getStatus() == PluginResult.Status.OK.ordinal()) { try { JSONObject result = new JSONObject(pluginResult.getStrMessage()); JSONObject distTags = result.getJSONObject("dist-tags"); String latestVersion = distTags.getString("latest"); if (latestVersion.equals(PLUGIN_VERSION) == false) { Log.i("CordovaLog", "phonegap-googlemaps-plugin version " + latestVersion + " is available."); } } catch (JSONException e) { } } } }); } catch (Exception e) { } } }); } cordova.getActivity().runOnUiThread(new Runnable() { @SuppressLint("NewApi") public void run() { /* try { Method method = webView.getClass().getMethod("getSettings"); WebSettings settings = (WebSettings)method.invoke(null); settings.setRenderPriority(RenderPriority.HIGH); settings.setCacheMode(WebSettings.LOAD_NO_CACHE); } catch (Exception e) { e.printStackTrace(); } */ if (Build.VERSION.SDK_INT >= 11) { webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); } root.setBackgroundColor(Color.WHITE); if (VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); } if (VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { Log.d(TAG, "Google Maps Plugin reloads the browser to change the background color as transparent."); webView.setBackgroundColor(0); try { Method method = webView.getClass().getMethod("reload"); method.invoke(webView); } catch (Exception e) { e.printStackTrace(); } } } }); } @Override public boolean execute(final String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException { if (isDebug) { if (args != null && args.length() > 0) { Log.d(TAG, "(debug)action=" + action + " args[0]=" + args.getString(0)); } else { Log.d(TAG, "(debug)action=" + action); } } Runnable runnable = new Runnable() { public void run() { if (("getMap".equals(action) == false && "isAvailable".equals(action) == false) && GoogleMaps.this.map == null) { Log.w(TAG, "Can not execute '" + action + "' because the map is not created."); return; } if ("exec".equals(action)) { try { String classMethod = args.getString(0); String[] params = classMethod.split("\\.", 0); if ("Map.setOptions".equals(classMethod)) { JSONObject jsonParams = args.getJSONObject(1); if (jsonParams.has("backgroundColor")) { JSONArray rgba = jsonParams.getJSONArray("backgroundColor"); int backgroundColor = Color.WHITE; if (rgba != null && rgba.length() == 4) { try { backgroundColor = PluginUtil.parsePluginColor(rgba); mPluginLayout.setBackgroundColor(backgroundColor); } catch (JSONException e) { } } } } // Load the class plugin GoogleMaps.this.loadPlugin(params[0]); PluginEntry entry = GoogleMaps.this.plugins.get(params[0]); if (params.length == 2 && entry != null) { entry.plugin.execute("execute", args, callbackContext); } else { callbackContext.error("'" + action + "' parameter is invalid length."); } } catch (Exception e) { e.printStackTrace(); callbackContext.error("Java Error\n" + e.getCause().getMessage()); } } else { try { Method method = GoogleMaps.this.getClass().getDeclaredMethod(action, JSONArray.class, CallbackContext.class); if (method.isAccessible() == false) { method.setAccessible(true); } method.invoke(GoogleMaps.this, args, callbackContext); } catch (Exception e) { e.printStackTrace(); callbackContext.error("'" + action + "' is not defined in GoogleMaps plugin."); } } } }; cordova.getActivity().runOnUiThread(runnable); return true; } @SuppressWarnings("unused") private void setDiv(JSONArray args, CallbackContext callbackContext) throws JSONException { if (args.length() == 0) { this.mapDivLayoutJSON = null; mPluginLayout.detachMyView(); this.sendNoResult(callbackContext); return; } if (args.length() == 2) { mPluginLayout.attachMyView(mapView); this.resizeMap(args, callbackContext); } } /** * Set visibility of the map * @param args * @param callbackContext * @throws JSONException */ @SuppressWarnings("unused") private void setVisible(JSONArray args, CallbackContext callbackContext) throws JSONException { boolean visible = args.getBoolean(0); if (this.windowLayer == null) { if (visible) { mapView.setVisibility(View.VISIBLE); } else { mapView.setVisibility(View.INVISIBLE); } } this.sendNoResult(callbackContext); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) private void getMap(JSONArray args, final CallbackContext callbackContext) throws JSONException { if (map != null) { callbackContext.success(); return; } mPluginLayout = new MyPluginLayout(webView, activity); // ------------------------------ // Check of Google Play Services // ------------------------------ int checkGooglePlayServices = GooglePlayServicesUtil.isGooglePlayServicesAvailable(activity); if (checkGooglePlayServices != ConnectionResult.SUCCESS) { // google play services is missing!!!! /* * Returns status code indicating whether there was an error. Can be one * of following in ConnectionResult: SUCCESS, SERVICE_MISSING, * SERVICE_VERSION_UPDATE_REQUIRED, SERVICE_DISABLED, SERVICE_INVALID. */ Log.e("CordovaLog", "---Google Play Services is not available: " + GooglePlayServicesUtil.getErrorString(checkGooglePlayServices)); Dialog errorDialog = null; try { //errorDialog = GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, activity, 1); Method getErrorDialogMethod = GooglePlayServicesUtil.class.getMethod("getErrorDialog", int.class, Activity.class, int.class); errorDialog = (Dialog) getErrorDialogMethod.invoke(null, checkGooglePlayServices, activity, 1); } catch (Exception e) { } ; if (errorDialog != null) { errorDialog.show(); } else { boolean isNeedToUpdate = false; String errorMsg = "Google Maps Android API v2 is not available for some reason on this device. Do you install the latest Google Play Services from Google Play Store?"; switch (checkGooglePlayServices) { //case ConnectionResult.DATE_INVALID: // errorMsg = "It seems your device date is set incorrectly. Please update the correct date and time."; // break; case ConnectionResult.DEVELOPER_ERROR: errorMsg = "The application is misconfigured. This error is not recoverable and will be treated as fatal. The developer should look at the logs after this to determine more actionable information."; break; case ConnectionResult.INTERNAL_ERROR: errorMsg = "An internal error of Google Play Services occurred. Please retry, and it should resolve the problem."; break; case ConnectionResult.INVALID_ACCOUNT: errorMsg = "You attempted to connect to the service with an invalid account name specified."; break; case ConnectionResult.LICENSE_CHECK_FAILED: errorMsg = "The application is not licensed to the user. This error is not recoverable and will be treated as fatal."; break; case ConnectionResult.NETWORK_ERROR: errorMsg = "A network error occurred. Please retry, and it should resolve the problem."; break; case ConnectionResult.SERVICE_DISABLED: errorMsg = "The installed version of Google Play services has been disabled on this device. Please turn on Google Play Services."; break; case ConnectionResult.SERVICE_INVALID: errorMsg = "The version of the Google Play services installed on this device is not authentic. Please update the Google Play Services from Google Play Store."; isNeedToUpdate = true; break; case ConnectionResult.SERVICE_MISSING: errorMsg = "Google Play services is missing on this device. Please install the Google Play Services."; isNeedToUpdate = true; break; case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED: errorMsg = "The installed version of Google Play services is out of date. Please update the Google Play Services from Google Play Store."; isNeedToUpdate = true; break; case ConnectionResult.SIGN_IN_REQUIRED: errorMsg = "You attempted to connect to the service but you are not signed in. Please check the Google Play Services configuration"; break; default: isNeedToUpdate = true; break; } final boolean finalIsNeedToUpdate = isNeedToUpdate; AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity); alertDialogBuilder.setMessage(errorMsg).setCancelable(false).setPositiveButton("Close", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); if (finalIsNeedToUpdate) { try { activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.android.gms"))); } catch (android.content.ActivityNotFoundException anfe) { activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse( "http://play.google.com/store/apps/details?id=appPackageName"))); } } } }); AlertDialog alertDialog = alertDialogBuilder.create(); // show it alertDialog.show(); } callbackContext.error("Google Play Services is not available."); return; } // Check the API key ApplicationInfo appliInfo = null; try { appliInfo = activity.getPackageManager().getApplicationInfo(activity.getPackageName(), PackageManager.GET_META_DATA); } catch (NameNotFoundException e) { } String API_KEY = appliInfo.metaData.getString("com.google.android.maps.v2.API_KEY"); if ("API_KEY_FOR_ANDROID".equals(API_KEY)) { AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity); alertDialogBuilder.setMessage( "Please replace 'API_KEY_FOR_ANDROID' in the platforms/android/AndroidManifest.xml with your API Key!") .setCancelable(false).setPositiveButton("Close", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); AlertDialog alertDialog = alertDialogBuilder.create(); // show it alertDialog.show(); } // ------------------------------ // Initialize Google Maps SDK // ------------------------------ try { MapsInitializer.initialize(activity); } catch (Exception e) { e.printStackTrace(); callbackContext.error(e.getMessage()); return; } GoogleMapOptions options = new GoogleMapOptions(); JSONObject params = args.getJSONObject(0); //background color if (params.has("backgroundColor")) { JSONArray rgba = params.getJSONArray("backgroundColor"); int backgroundColor = Color.WHITE; if (rgba != null && rgba.length() == 4) { try { backgroundColor = PluginUtil.parsePluginColor(rgba); this.mPluginLayout.setBackgroundColor(backgroundColor); } catch (JSONException e) { } } } //controls if (params.has("controls")) { JSONObject controls = params.getJSONObject("controls"); if (controls.has("compass")) { options.compassEnabled(controls.getBoolean("compass")); } if (controls.has("zoom")) { options.zoomControlsEnabled(controls.getBoolean("zoom")); } } //gestures if (params.has("gestures")) { JSONObject gestures = params.getJSONObject("gestures"); if (gestures.has("tilt")) { options.tiltGesturesEnabled(gestures.getBoolean("tilt")); } if (gestures.has("scroll")) { options.scrollGesturesEnabled(gestures.getBoolean("scroll")); } if (gestures.has("rotate")) { options.rotateGesturesEnabled(gestures.getBoolean("rotate")); } if (gestures.has("zoom")) { options.zoomGesturesEnabled(gestures.getBoolean("zoom")); } } // map type if (params.has("mapType")) { String typeStr = params.getString("mapType"); int mapTypeId = -1; mapTypeId = typeStr.equals("MAP_TYPE_NORMAL") ? GoogleMap.MAP_TYPE_NORMAL : mapTypeId; mapTypeId = typeStr.equals("MAP_TYPE_HYBRID") ? GoogleMap.MAP_TYPE_HYBRID : mapTypeId; mapTypeId = typeStr.equals("MAP_TYPE_SATELLITE") ? GoogleMap.MAP_TYPE_SATELLITE : mapTypeId; mapTypeId = typeStr.equals("MAP_TYPE_TERRAIN") ? GoogleMap.MAP_TYPE_TERRAIN : mapTypeId; mapTypeId = typeStr.equals("MAP_TYPE_NONE") ? GoogleMap.MAP_TYPE_NONE : mapTypeId; if (mapTypeId != -1) { options.mapType(mapTypeId); } } // initial camera position if (params.has("camera")) { JSONObject camera = params.getJSONObject("camera"); Builder builder = CameraPosition.builder(); if (camera.has("bearing")) { builder.bearing((float) camera.getDouble("bearing")); } if (camera.has("latLng")) { JSONObject latLng = camera.getJSONObject("latLng"); builder.target(new LatLng(latLng.getDouble("lat"), latLng.getDouble("lng"))); } if (camera.has("tilt")) { builder.tilt((float) camera.getDouble("tilt")); } if (camera.has("zoom")) { builder.zoom((float) camera.getDouble("zoom")); } options.camera(builder.build()); } mapView = new MapView(activity, options); mapView.onCreate(null); mapView.onResume(); map = mapView.getMap(); //controls if (params.has("controls")) { JSONObject controls = params.getJSONObject("controls"); if (controls.has("myLocationButton")) { Boolean isEnabled = controls.getBoolean("myLocationButton"); map.setMyLocationEnabled(isEnabled); map.getUiSettings().setMyLocationButtonEnabled(isEnabled); } if (controls.has("indoorPicker")) { Boolean isEnabled = controls.getBoolean("indoorPicker"); map.setIndoorEnabled(isEnabled); } } // Set event listener map.setOnCameraChangeListener(this); map.setOnInfoWindowClickListener(this); map.setOnMapClickListener(this); map.setOnMapLoadedCallback(this); map.setOnMapLongClickListener(this); map.setOnMarkerClickListener(this); map.setOnMarkerDragListener(this); map.setOnMyLocationButtonClickListener(this); // Load PluginMap class this.loadPlugin("Map"); //Custom info window map.setInfoWindowAdapter(this); callbackContext.success(); // ------------------------------ // Embed the map if a container is specified. // ------------------------------ if (args.length() == 3) { this.mapDivLayoutJSON = args.getJSONObject(1); mPluginLayout.attachMyView(mapView); this.resizeMap(args, callbackContext); } } private float contentToView(long d) { return d * this.density; } //----------------------------------- // Create the instance of class //----------------------------------- @SuppressWarnings("rawtypes") private void loadPlugin(String serviceName) { if (plugins.containsKey(serviceName)) { return; } try { Class pluginCls = Class.forName("plugin.google.maps.Plugin" + serviceName); CordovaPlugin plugin = (CordovaPlugin) pluginCls.newInstance(); PluginEntry pluginEntry = new PluginEntry("GoogleMaps", plugin); this.plugins.put(serviceName, pluginEntry); try { Class cordovaPref = Class.forName("org.apache.cordova.CordovaPreferences"); if (cordovaPref != null) { Method privateInit = CordovaPlugin.class.getMethod("privateInitialize", CordovaInterface.class, CordovaWebView.class, cordovaPref); if (privateInit != null) { privateInit.invoke(plugin, this.cordova, webView, null); } } } catch (Exception e2) { } plugin.initialize(this.cordova, webView); ((MyPluginInterface) plugin).setMapCtrl(this); if (map == null) { Log.e(TAG, "map is null!"); } } catch (Exception e) { e.printStackTrace(); } } @SuppressWarnings("unused") private Boolean myTest(JSONArray args, CallbackContext callbackContext) { PolygonOptions options = new PolygonOptions(); options.add(new LatLng(-45, -90)); options.add(new LatLng(-45, -180)); options.add(new LatLng(0, -180)); options.add(new LatLng(0, -90)); map.addPolygon(options); callbackContext.success(); return true; } @SuppressWarnings("unused") private Boolean getLicenseInfo(JSONArray args, CallbackContext callbackContext) { String msg = GooglePlayServicesUtil.getOpenSourceSoftwareLicenseInfo(activity); callbackContext.success(msg); return true; } @Override public Object onMessage(String id, Object data) { EVENTS event = null; try { event = EVENTS.valueOf(id); } catch (Exception e) { } if (event == null) { return null; } switch (event) { case onScrollChanged: ScrollEvent scrollEvent = (ScrollEvent) data; if (mPluginLayout != null) { mPluginLayout.scrollTo(scrollEvent.nl, scrollEvent.nt); if (mapDivLayoutJSON != null) { try { float divW = contentToView(mapDivLayoutJSON.getLong("width")); float divH = contentToView(mapDivLayoutJSON.getLong("height")); float divLeft = contentToView(mapDivLayoutJSON.getLong("left")); float divTop = contentToView(mapDivLayoutJSON.getLong("top")); mPluginLayout.setDrawingRect(divLeft, divTop - scrollEvent.nt, divLeft + divW, divTop + divH - scrollEvent.nt); } catch (JSONException e) { e.printStackTrace(); } } } break; } return null; } private void closeWindow() { try { Method method = webView.getClass().getMethod("hideCustomView"); method.invoke(null); } catch (Exception e) { e.printStackTrace(); } } @SuppressWarnings("unused") private void showDialog(final JSONArray args, final CallbackContext callbackContext) { if (windowLayer != null) { return; } // window layout windowLayer = new LinearLayout(activity); windowLayer.setPadding(0, 0, 0, 0); LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); layoutParams.gravity = Gravity.TOP | Gravity.LEFT; windowLayer.setLayoutParams(layoutParams); // dialog window layer FrameLayout dialogLayer = new FrameLayout(activity); dialogLayer.setLayoutParams(layoutParams); //dialogLayer.setPadding(15, 15, 15, 0); dialogLayer.setBackgroundColor(Color.LTGRAY); windowLayer.addView(dialogLayer); // map frame final FrameLayout mapFrame = new FrameLayout(activity); mapFrame.setPadding(0, 0, 0, (int) (40 * density)); dialogLayer.addView(mapFrame); if (this.mPluginLayout != null && this.mPluginLayout.getMyView() != null) { this.mPluginLayout.detachMyView(); } ViewGroup.LayoutParams lParams = (ViewGroup.LayoutParams) mapView.getLayoutParams(); if (lParams == null) { lParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); } lParams.width = ViewGroup.LayoutParams.MATCH_PARENT; lParams.height = ViewGroup.LayoutParams.MATCH_PARENT; if (lParams instanceof AbsoluteLayout.LayoutParams) { AbsoluteLayout.LayoutParams params = (AbsoluteLayout.LayoutParams) lParams; params.x = 0; params.y = 0; mapView.setLayoutParams(params); } else if (lParams instanceof LinearLayout.LayoutParams) { LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) lParams; params.topMargin = 0; params.leftMargin = 0; mapView.setLayoutParams(params); } else if (lParams instanceof FrameLayout.LayoutParams) { FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) lParams; params.topMargin = 0; params.leftMargin = 0; mapView.setLayoutParams(params); } mapFrame.addView(this.mapView); // button frame LinearLayout buttonFrame = new LinearLayout(activity); buttonFrame.setOrientation(LinearLayout.HORIZONTAL); buttonFrame.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); LinearLayout.LayoutParams buttonFrameParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); buttonFrame.setLayoutParams(buttonFrameParams); dialogLayer.addView(buttonFrame); //close button LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1.0f); TextView closeLink = new TextView(activity); closeLink.setText("Close"); closeLink.setLayoutParams(buttonParams); closeLink.setTextColor(Color.BLUE); closeLink.setTextSize(20); closeLink.setGravity(Gravity.LEFT); closeLink.setPadding((int) (10 * density), 0, 0, (int) (10 * density)); closeLink.setOnClickListener(GoogleMaps.this); closeLink.setId(CLOSE_LINK_ID); buttonFrame.addView(closeLink); //license button TextView licenseLink = new TextView(activity); licenseLink.setText("Legal Notices"); licenseLink.setTextColor(Color.BLUE); licenseLink.setLayoutParams(buttonParams); licenseLink.setTextSize(20); licenseLink.setGravity(Gravity.RIGHT); licenseLink.setPadding((int) (10 * density), (int) (20 * density), (int) (10 * density), (int) (10 * density)); licenseLink.setOnClickListener(GoogleMaps.this); licenseLink.setId(LICENSE_LINK_ID); buttonFrame.addView(licenseLink); webView.setVisibility(View.GONE); root.addView(windowLayer); //Dummy view for the back-button event FrameLayout dummyLayout = new FrameLayout(activity); /* this.webView.showCustomView(dummyLayout, new WebChromeClient.CustomViewCallback() { @Override public void onCustomViewHidden() { mapFrame.removeView(mapView); if (mPluginLayout != null && mapDivLayoutJSON != null) { mPluginLayout.attachMyView(mapView); mPluginLayout.updateViewPosition(); } root.removeView(windowLayer); webView.setVisibility(View.VISIBLE); windowLayer = null; GoogleMaps.this.onMapEvent("map_close"); } }); */ this.sendNoResult(callbackContext); } private void resizeMap(JSONArray args, CallbackContext callbackContext) throws JSONException { if (mPluginLayout == null) { callbackContext.success(); return; } mapDivLayoutJSON = args.getJSONObject(args.length() - 2); JSONArray HTMLs = args.getJSONArray(args.length() - 1); JSONObject elemInfo, elemSize; String elemId; float divW, divH, divLeft, divTop; if (mPluginLayout == null) { this.sendNoResult(callbackContext); return; } this.mPluginLayout.clearHTMLElement(); for (int i = 0; i < HTMLs.length(); i++) { elemInfo = HTMLs.getJSONObject(i); try { elemId = elemInfo.getString("id"); elemSize = elemInfo.getJSONObject("size"); divW = contentToView(elemSize.getLong("width")); divH = contentToView(elemSize.getLong("height")); divLeft = contentToView(elemSize.getLong("left")); divTop = contentToView(elemSize.getLong("top")); mPluginLayout.putHTMLElement(elemId, divLeft, divTop, divLeft + divW, divTop + divH); } catch (Exception e) { e.printStackTrace(); } } //mPluginLayout.inValidate(); updateMapViewLayout(); this.sendNoResult(callbackContext); } private void updateMapViewLayout() { if (mPluginLayout == null) { return; } try { float divW = contentToView(mapDivLayoutJSON.getLong("width")); float divH = contentToView(mapDivLayoutJSON.getLong("height")); float divLeft = contentToView(mapDivLayoutJSON.getLong("left")); float divTop = contentToView(mapDivLayoutJSON.getLong("top")); // Update the plugin drawing view rect mPluginLayout.setDrawingRect(divLeft, divTop - webView.getScrollY(), divLeft + divW, divTop + divH - webView.getScrollY()); mPluginLayout.updateViewPosition(); mapView.requestLayout(); } catch (JSONException e) { e.printStackTrace(); } } @SuppressWarnings("unused") private void closeDialog(final JSONArray args, final CallbackContext callbackContext) { this.closeWindow(); this.sendNoResult(callbackContext); } @SuppressWarnings("unused") private void isAvailable(final JSONArray args, final CallbackContext callbackContext) throws JSONException { // ------------------------------ // Check of Google Play Services // ------------------------------ int checkGooglePlayServices = GooglePlayServicesUtil.isGooglePlayServicesAvailable(activity); if (checkGooglePlayServices != ConnectionResult.SUCCESS) { // google play services is missing!!!! callbackContext.error( "Google Maps Android API v2 is not available, because this device does not have Google Play Service."); return; } // ------------------------------ // Check of Google Maps Android API v2 // ------------------------------ try { @SuppressWarnings({ "rawtypes" }) Class GoogleMapsClass = Class.forName("com.google.android.gms.maps.GoogleMap"); } catch (Exception e) { Log.e("GoogleMaps", "Error", e); callbackContext.error(e.getMessage()); return; } callbackContext.success(); } @SuppressWarnings("unused") private void getMyLocation(final JSONArray args, final CallbackContext callbackContext) throws JSONException { LocationManager locationManager = (LocationManager) this.activity .getSystemService(Context.LOCATION_SERVICE); List<String> providers = locationManager.getAllProviders(); if (providers.size() == 0) { JSONObject result = new JSONObject(); result.put("status", false); result.put("error_code", "not_available"); result.put("error_message", "Since this device does not have any location provider, this app can not detect your location."); callbackContext.error(result); return; } // enableHighAccuracy = true -> PRIORITY_HIGH_ACCURACY // enableHighAccuracy = false -> PRIORITY_BALANCED_POWER_ACCURACY JSONObject params = args.getJSONObject(0); boolean isHigh = false; if (params.has("enableHighAccuracy")) { isHigh = params.getBoolean("enableHighAccuracy"); } final boolean enableHighAccuracy = isHigh; String provider = null; if (enableHighAccuracy == true) { if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { provider = LocationManager.GPS_PROVIDER; } else if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { provider = LocationManager.NETWORK_PROVIDER; } else if (locationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER)) { provider = LocationManager.PASSIVE_PROVIDER; } } else { if (locationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER)) { provider = LocationManager.PASSIVE_PROVIDER; } else if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { provider = LocationManager.NETWORK_PROVIDER; } else if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { provider = LocationManager.GPS_PROVIDER; } } if (provider == null) { //Ask the user to turn on the location services. AlertDialog.Builder builder = new AlertDialog.Builder(this.activity); builder.setTitle("Improve location accuracy"); builder.setMessage("To enhance your Maps experience:\n\n" + " - Enable Google apps location access\n\n" + " - Turn on GPS and mobile network location"); builder.setPositiveButton("Settings", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //Launch settings, allowing user to make a change Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); activity.startActivity(intent); JSONObject result = new JSONObject(); try { result.put("status", false); result.put("error_code", "open_settings"); result.put("error_message", "User opened the settings of location service. So try again."); } catch (JSONException e) { } callbackContext.error(result); } }); builder.setNegativeButton("Skip", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //No location service, no Activity dialog.dismiss(); JSONObject result = new JSONObject(); try { result.put("status", false); result.put("error_code", "service_denied"); result.put("error_message", "This app has rejected to use Location Services."); } catch (JSONException e) { } callbackContext.error(result); } }); builder.create().show(); return; } Location location = locationManager.getLastKnownLocation(provider); if (location != null) { JSONObject result = PluginUtil.location2Json(location); result.put("status", true); callbackContext.success(result); return; } PluginResult tmpResult = new PluginResult(PluginResult.Status.NO_RESULT); tmpResult.setKeepCallback(true); callbackContext.sendPluginResult(tmpResult); locationClient = new LocationClient(this.activity, new ConnectionCallbacks() { @Override public void onConnected(Bundle bundle) { LocationRequest request = new LocationRequest(); int priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY; if (enableHighAccuracy) { priority = LocationRequest.PRIORITY_HIGH_ACCURACY; } request.setPriority(priority); locationClient.requestLocationUpdates(request, new LocationListener() { @Override public void onLocationChanged(Location location) { JSONObject result; try { result = PluginUtil.location2Json(location); result.put("status", true); callbackContext.success(result); } catch (JSONException e) { } locationClient.disconnect(); } }); } @Override public void onDisconnected() { } }, new OnConnectionFailedListener() { @Override public void onConnectionFailed(ConnectionResult connectionResult) { int errorCode = connectionResult.getErrorCode(); String errorMsg = GooglePlayServicesUtil.getErrorString(errorCode); PluginResult result = new PluginResult(PluginResult.Status.ERROR, errorMsg); callbackContext.sendPluginResult(result); } }); locationClient.connect(); } private void showLicenseText() { AsyncLicenseInfo showLicense = new AsyncLicenseInfo(activity); showLicense.execute(); } /******************************************************** * Callbacks ********************************************************/ /** * Notify marker event to JS * @param eventName * @param marker */ private void onMarkerEvent(String eventName, Marker marker) { String markerId = "marker_" + marker.getId(); webView.loadUrl( "javascript:plugin.google.maps.Map." + "_onMarkerEvent('" + eventName + "','" + markerId + "')"); } private void onOverlayEvent(String eventName, String overlayId, LatLng point) { webView.loadUrl("javascript:plugin.google.maps.Map." + "_onOverlayEvent(" + "'" + eventName + "','" + overlayId + "', " + "new window.plugin.google.maps.LatLng(" + point.latitude + "," + point.longitude + ")" + ")"); } private void onPolylineClick(Polyline polyline, LatLng point) { String overlayId = "polyline_" + polyline.getId(); this.onOverlayEvent("overlay_click", overlayId, point); } private void onPolygonClick(Polygon polygon, LatLng point) { String overlayId = "polygon_" + polygon.getId(); this.onOverlayEvent("overlay_click", overlayId, point); } private void onCircleClick(Circle circle, LatLng point) { String overlayId = "circle_" + circle.getId(); this.onOverlayEvent("overlay_click", overlayId, point); } private void onGroundOverlayClick(GroundOverlay groundOverlay, LatLng point) { String overlayId = "groundOverlay_" + groundOverlay.getId(); this.onOverlayEvent("overlay_click", overlayId, point); } @Override public boolean onMarkerClick(Marker marker) { this.onMarkerEvent("click", marker); JSONObject properties = null; String propertyId = "marker_property_" + marker.getId(); PluginEntry pluginEntry = this.plugins.get("Marker"); PluginMarker pluginMarker = (PluginMarker) pluginEntry.plugin; if (pluginMarker.objects.containsKey(propertyId)) { properties = (JSONObject) pluginMarker.objects.get(propertyId); if (properties.has("disableAutoPan")) { boolean disableAutoPan = false; try { disableAutoPan = properties.getBoolean("disableAutoPan"); } catch (JSONException e) { } if (disableAutoPan) { marker.showInfoWindow(); return true; } } } marker.showInfoWindow(); return true; //return false; } @Override public void onInfoWindowClick(Marker marker) { this.onMarkerEvent("info_click", marker); } @Override public void onMarkerDrag(Marker marker) { this.onMarkerEvent("drag", marker); } @Override public void onMarkerDragEnd(Marker marker) { this.onMarkerEvent("drag_end", marker); } @Override public void onMarkerDragStart(Marker marker) { this.onMarkerEvent("drag_start", marker); } /** * Notify map event to JS * @param eventName * @param point */ private void onMapEvent(final String eventName) { webView.loadUrl("javascript:plugin.google.maps.Map._onMapEvent('" + eventName + "')"); } /** * Notify map event to JS * @param eventName * @param point */ private void onMapEvent(final String eventName, final LatLng point) { webView.loadUrl("javascript:plugin.google.maps.Map._onMapEvent(" + "'" + eventName + "', new window.plugin.google.maps.LatLng(" + point.latitude + "," + point.longitude + "))"); } @Override public void onMapLongClick(LatLng point) { this.onMapEvent("long_click", point); } private double calculateDistance(LatLng pt1, LatLng pt2) { float[] results = new float[1]; Location.distanceBetween(pt1.latitude, pt1.longitude, pt2.latitude, pt2.longitude, results); return results[0]; } /** * Notify map click event to JS, also checks for click on a polygon and triggers onPolygonEvent * @param point */ public void onMapClick(LatLng point) { boolean hitPoly = false; String key; LatLngBounds bounds; // Polyline PluginEntry polylinePlugin = this.plugins.get("Polyline"); if (polylinePlugin != null) { PluginPolyline polylineClass = (PluginPolyline) polylinePlugin.plugin; List<LatLng> points; Polyline polyline; Point origin = new Point(); Point hitArea = new Point(); hitArea.x = 1; hitArea.y = 1; Projection projection = map.getProjection(); double threshold = this.calculateDistance(projection.fromScreenLocation(origin), projection.fromScreenLocation(hitArea)); for (HashMap.Entry<String, Object> entry : polylineClass.objects.entrySet()) { key = entry.getKey(); if (key.contains("polyline_bounds_")) { bounds = (LatLngBounds) entry.getValue(); if (bounds.contains(point)) { key = key.replace("bounds_", ""); polyline = polylineClass.getPolyline(key); points = polyline.getPoints(); if (polyline.isGeodesic()) { if (this.isPointOnTheGeodesicLine(points, point, threshold)) { hitPoly = true; this.onPolylineClick(polyline, point); } } else { if (this.isPointOnTheLine(points, point)) { hitPoly = true; this.onPolylineClick(polyline, point); } } } } } if (hitPoly) { return; } } // Loop through all polygons to check if within the touch point PluginEntry polygonPlugin = this.plugins.get("Polygon"); if (polygonPlugin != null) { PluginPolygon polygonClass = (PluginPolygon) polygonPlugin.plugin; for (HashMap.Entry<String, Object> entry : polygonClass.objects.entrySet()) { key = entry.getKey(); if (key.contains("polygon_bounds_")) { bounds = (LatLngBounds) entry.getValue(); if (bounds.contains(point)) { key = key.replace("_bounds", ""); Polygon polygon = polygonClass.getPolygon(key); if (this.isPolygonContains(polygon.getPoints(), point)) { hitPoly = true; this.onPolygonClick(polygon, point); } } } } if (hitPoly) { return; } } // Loop through all circles to check if within the touch point PluginEntry circlePlugin = this.plugins.get("Circle"); if (circlePlugin != null) { PluginCircle circleClass = (PluginCircle) circlePlugin.plugin; for (HashMap.Entry<String, Object> entry : circleClass.objects.entrySet()) { Circle circle = (Circle) entry.getValue(); if (this.isCircleContains(circle, point)) { hitPoly = true; this.onCircleClick(circle, point); } } if (hitPoly) { return; } } // Loop through ground overlays to check if within the touch point PluginEntry groundOverlayPlugin = this.plugins.get("GroundOverlay"); if (groundOverlayPlugin != null) { PluginGroundOverlay groundOverlayClass = (PluginGroundOverlay) groundOverlayPlugin.plugin; for (HashMap.Entry<String, Object> entry : groundOverlayClass.objects.entrySet()) { GroundOverlay groundOverlay = (GroundOverlay) entry.getValue(); if (this.isGroundOverlayContains(groundOverlay, point)) { hitPoly = true; this.onGroundOverlayClick(groundOverlay, point); } } if (hitPoly) { return; } } // Only emit click event if no overlays hit this.onMapEvent("click", point); } /** * Intersection for geodesic line * @ref http://my-clip-devdiary.blogspot.com/2014/01/html5canvas.html * * @param points * @param point * @param threshold * @return */ private boolean isPointOnTheGeodesicLine(List<LatLng> points, LatLng point, double threshold) { double trueDistance, testDistance1, testDistance2; Point p0, p1, touchPoint; touchPoint = new Point(); touchPoint.x = (int) (point.latitude * 100000); touchPoint.y = (int) (point.longitude * 100000); for (int i = 0; i < points.size() - 1; i++) { p0 = new Point(); p0.x = (int) (points.get(i).latitude * 100000); p0.y = (int) (points.get(i).longitude * 100000); p1 = new Point(); p1.x = (int) (points.get(i + 1).latitude * 100000); p1.y = (int) (points.get(i + 1).longitude * 100000); trueDistance = this.calculateDistance(points.get(i), points.get(i + 1)); testDistance1 = this.calculateDistance(points.get(i), point); testDistance2 = this.calculateDistance(point, points.get(i + 1)); // the distance is exactly same if the point is on the straight line if (Math.abs(trueDistance - (testDistance1 + testDistance2)) < threshold) { return true; } } return false; } /** * Intersection for non-geodesic line * @ref http://movingahead.seesaa.net/article/299962216.html * @ref http://www.softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm#Line-Plane * * @param points * @param point * @return */ private boolean isPointOnTheLine(List<LatLng> points, LatLng point) { double Sx, Sy; Projection projection = map.getProjection(); Point p0, p1, touchPoint; touchPoint = projection.toScreenLocation(point); p0 = projection.toScreenLocation(points.get(0)); for (int i = 1; i < points.size(); i++) { p1 = projection.toScreenLocation(points.get(i)); Sx = ((double) touchPoint.x - (double) p0.x) / ((double) p1.x - (double) p0.x); Sy = ((double) touchPoint.y - (double) p0.y) / ((double) p1.y - (double) p0.y); if (Math.abs(Sx - Sy) < 0.05 && Sx < 1 && Sx > 0) { return true; } p0 = p1; } return false; } /** * Intersects using thw Winding Number Algorithm * @ref http://www.nttpc.co.jp/company/r_and_d/technology/number_algorithm.html * @param path * @param point * @return */ private boolean isPolygonContains(List<LatLng> path, LatLng point) { int wn = 0; Projection projection = map.getProjection(); VisibleRegion visibleRegion = projection.getVisibleRegion(); LatLngBounds bounds = visibleRegion.latLngBounds; Point sw = projection.toScreenLocation(bounds.southwest); Point touchPoint = projection.toScreenLocation(point); touchPoint.y = sw.y - touchPoint.y; double vt; for (int i = 0; i < path.size() - 1; i++) { Point a = projection.toScreenLocation(path.get(i)); a.y = sw.y - a.y; Point b = projection.toScreenLocation(path.get(i + 1)); b.y = sw.y - b.y; if ((a.y <= touchPoint.y) && (b.y > touchPoint.y)) { vt = ((double) touchPoint.y - (double) a.y) / ((double) b.y - (double) a.y); if (touchPoint.x < ((double) a.x + (vt * ((double) b.x - (double) a.x)))) { wn++; } } else if ((a.y > touchPoint.y) && (b.y <= touchPoint.y)) { vt = ((double) touchPoint.y - (double) a.y) / ((double) b.y - (double) a.y); if (touchPoint.x < ((double) a.x + (vt * ((double) b.x - (double) a.x)))) { wn--; } } } return (wn != 0); } /** * Check if a circle contains a point * @param circle * @param point */ private boolean isCircleContains(Circle circle, LatLng point) { double r = circle.getRadius(); LatLng center = circle.getCenter(); double cX = center.latitude; double cY = center.longitude; double pX = point.latitude; double pY = point.longitude; float[] results = new float[1]; Location.distanceBetween(cX, cY, pX, pY, results); if (results[0] < r) { return true; } else { return false; } } /** * Check if a ground overlay contains a point * @param groundOverlay * @param point */ private boolean isGroundOverlayContains(GroundOverlay groundOverlay, LatLng point) { LatLngBounds groundOverlayBounds = groundOverlay.getBounds(); return groundOverlayBounds.contains(point); } @Override public boolean onMyLocationButtonClick() { webView.loadUrl("javascript:plugin.google.maps.Map._onMapEvent('my_location_button_click')"); return false; } @Override public void onMapLoaded() { webView.loadUrl("javascript:plugin.google.maps.Map._onMapEvent('map_loaded')"); } /** * Notify the myLocationChange event to JS */ @Override public void onCameraChange(CameraPosition position) { JSONObject params = new JSONObject(); String jsonStr = ""; try { JSONObject target = new JSONObject(); target.put("lat", position.target.latitude); target.put("lng", position.target.longitude); params.put("target", target); params.put("hashCode", position.hashCode()); params.put("bearing", position.bearing); params.put("tilt", position.tilt); params.put("zoom", position.zoom); jsonStr = params.toString(); } catch (JSONException e) { e.printStackTrace(); } webView.loadUrl("javascript:plugin.google.maps.Map._onCameraEvent('camera_change', " + jsonStr + ")"); } @Override public void onPause(boolean multitasking) { if (mapView != null) { mapView.onPause(); } super.onPause(multitasking); } @Override public void onResume(boolean multitasking) { if (mapView != null) { mapView.onResume(); } super.onResume(multitasking); } @Override public void onDestroy() { if (mapView != null) { mapView.onDestroy(); } super.onDestroy(); } @Override public void onClick(View view) { int viewId = view.getId(); if (viewId == CLOSE_LINK_ID) { closeWindow(); return; } if (viewId == LICENSE_LINK_ID) { showLicenseText(); return; } } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) @Override public View getInfoContents(Marker marker) { String title = marker.getTitle(); String snippet = marker.getSnippet(); if ((title == null) && (snippet == null)) { return null; } JSONObject properties = null; JSONObject styles = null; String propertyId = "marker_property_" + marker.getId(); PluginEntry pluginEntry = this.plugins.get("Marker"); PluginMarker pluginMarker = (PluginMarker) pluginEntry.plugin; if (pluginMarker.objects.containsKey(propertyId)) { properties = (JSONObject) pluginMarker.objects.get(propertyId); if (properties.has("styles")) { try { styles = (JSONObject) properties.getJSONObject("styles"); } catch (JSONException e) { } } } // Linear layout LinearLayout windowLayer = new LinearLayout(activity); windowLayer.setPadding(3, 3, 3, 3); windowLayer.setOrientation(LinearLayout.VERTICAL); LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER; windowLayer.setLayoutParams(layoutParams); //---------------------------------------- // text-align = left | center | right //---------------------------------------- int gravity = Gravity.LEFT; int textAlignment = View.TEXT_ALIGNMENT_GRAVITY; if (styles != null) { try { String textAlignValue = styles.getString("text-align"); switch (TEXT_STYLE_ALIGNMENTS.valueOf(textAlignValue)) { case left: gravity = Gravity.LEFT; textAlignment = View.TEXT_ALIGNMENT_GRAVITY; break; case center: gravity = Gravity.CENTER; textAlignment = View.TEXT_ALIGNMENT_CENTER; break; case right: gravity = Gravity.RIGHT; textAlignment = View.TEXT_ALIGNMENT_VIEW_END; break; } } catch (Exception e) { } } if (title != null) { if (title.indexOf("data:image/") > -1 && title.indexOf(";base64,") > -1) { String[] tmp = title.split(","); Bitmap image = PluginUtil.getBitmapFromBase64encodedImage(tmp[1]); image = PluginUtil.scaleBitmapForDevice(image); ImageView imageView = new ImageView(this.cordova.getActivity()); imageView.setImageBitmap(image); windowLayer.addView(imageView); } else { TextView textView = new TextView(this.cordova.getActivity()); textView.setText(title); textView.setSingleLine(false); int titleColor = Color.BLACK; if (styles != null && styles.has("color")) { try { titleColor = PluginUtil.parsePluginColor(styles.getJSONArray("color")); } catch (JSONException e) { } } textView.setTextColor(titleColor); textView.setGravity(gravity); if (VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { textView.setTextAlignment(textAlignment); } //---------------------------------------- // font-style = normal | italic // font-weight = normal | bold //---------------------------------------- int fontStyle = Typeface.NORMAL; if (styles != null) { try { if ("italic".equals(styles.getString("font-style"))) { fontStyle = Typeface.ITALIC; } } catch (JSONException e) { } try { if ("bold".equals(styles.getString("font-weight"))) { fontStyle = fontStyle | Typeface.BOLD; } } catch (JSONException e) { } } textView.setTypeface(Typeface.DEFAULT, fontStyle); windowLayer.addView(textView); } } if (snippet != null) { //snippet = snippet.replaceAll("\n", ""); TextView textView2 = new TextView(this.cordova.getActivity()); textView2.setText(snippet); textView2.setTextColor(Color.GRAY); textView2.setTextSize((textView2.getTextSize() / 6 * 5) / density); textView2.setGravity(gravity); if (VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { textView2.setTextAlignment(textAlignment); } windowLayer.addView(textView2); } return windowLayer; } @Override public View getInfoWindow(Marker marker) { return null; } /** * Clear all markups * @param args * @param callbackContext * @throws JSONException */ @SuppressWarnings("unused") private void clear(JSONArray args, CallbackContext callbackContext) throws JSONException { Set<String> pluginNames = plugins.keySet(); Iterator<String> iterator = pluginNames.iterator(); String pluginName; PluginEntry pluginEntry; while (iterator.hasNext()) { pluginName = iterator.next(); if ("Map".equals(pluginName) == false) { pluginEntry = plugins.get(pluginName); ((MyPlugin) pluginEntry.plugin).clear(); } } this.map.clear(); this.sendNoResult(callbackContext); } @SuppressWarnings("unused") private void pluginLayer_pushHtmlElement(JSONArray args, CallbackContext callbackContext) throws JSONException { if (mPluginLayout != null) { String domId = args.getString(0); JSONObject elemSize = args.getJSONObject(1); float left = contentToView(elemSize.getLong("left")); float top = contentToView(elemSize.getLong("top")); float width = contentToView(elemSize.getLong("width")); float height = contentToView(elemSize.getLong("height")); mPluginLayout.putHTMLElement(domId, left, top, (left + width), (top + height)); this.mPluginLayout.inValidate(); } this.sendNoResult(callbackContext); } @SuppressWarnings("unused") private void pluginLayer_removeHtmlElement(JSONArray args, CallbackContext callbackContext) throws JSONException { if (mPluginLayout != null) { String domId = args.getString(0); mPluginLayout.removeHTMLElement(domId); this.mPluginLayout.inValidate(); } this.sendNoResult(callbackContext); } /** * Set click-ability of the map * @param args * @param callbackContext * @throws JSONException */ @SuppressWarnings("unused") private void pluginLayer_setClickable(JSONArray args, CallbackContext callbackContext) throws JSONException { boolean clickable = args.getBoolean(0); if (mapView != null && this.windowLayer == null) { this.mPluginLayout.setClickable(clickable); } this.sendNoResult(callbackContext); } /** * Set the app background * @param args * @param callbackContext * @throws JSONException */ @SuppressWarnings("unused") private void pluginLayer_setBackGroundColor(JSONArray args, CallbackContext callbackContext) throws JSONException { if (mPluginLayout != null) { JSONArray rgba = args.getJSONArray(0); int backgroundColor = Color.WHITE; if (rgba != null && rgba.length() == 4) { try { backgroundColor = PluginUtil.parsePluginColor(rgba); this.mPluginLayout.setBackgroundColor(backgroundColor); } catch (JSONException e) { } } } this.sendNoResult(callbackContext); } /** * Set the debug flag of myPluginLayer * @param args * @param callbackContext * @throws JSONException */ @SuppressWarnings("unused") private void pluginLayer_setDebuggable(JSONArray args, CallbackContext callbackContext) throws JSONException { boolean debuggable = args.getBoolean(0); if (mapView != null && this.windowLayer == null) { this.mPluginLayout.setDebug(debuggable); } this.sendNoResult(callbackContext); } /** * Destroy the map completely * @param args * @param callbackContext */ @SuppressWarnings("unused") private void remove(JSONArray args, CallbackContext callbackContext) { if (mPluginLayout != null) { this.mPluginLayout.setClickable(false); this.mPluginLayout.detachMyView(); this.mPluginLayout = null; } plugins.clear(); if (map != null) { map.setMyLocationEnabled(false); map.clear(); } if (mapView != null) { mapView.onDestroy(); } map = null; mapView = null; windowLayer = null; mapDivLayoutJSON = null; System.gc(); this.sendNoResult(callbackContext); } protected void sendNoResult(CallbackContext callbackContext) { PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT); callbackContext.sendPluginResult(pluginResult); } }