URLImage on MapContainer not displayed on actual device and flickering in simulator - google-maps

My app features a map, on which the user's avatar is displayed in the center and where markers including photo should be added when the user moves the map.
On the simulator, the markers are added but the images disappear as soon as I release the pointer then only the placeholders remain (this is what I call flickering). On the device, nothing is shown apart from the user's avatar.
As you can see the image does not remain on the map, only the placeholder does. The user icon is southern on the map but it is shown.
Please note: I am not receiving 404 errors and there is only one listener on the map (see below):
Here is how I trigger the map update:
googleMap.addMapListener((source, zoom, center) -> {
showReportsOnMap(googleMap, center, theme, currentForm, selectCategoryButton.getWidth());
});
And here is how I add the reports the map:
public void showReportsOnMap(
MapContainer currentMap,
Coord center,
Resources theme,
Form f,
int reportImageWidth) {
/**
* Get the map borders (CAUTION : it can be NaN)
*/
Coord NE = currentMap.getCoordAtPosition(currentMap.getAbsoluteX() + currentMap.getWidth(), currentMap.getAbsoluteY());
Coord SW = currentMap.getCoordAtPosition(currentMap.getAbsoluteX(), currentMap.getAbsoluteY() + currentMap.getHeight());
boolean bordersKnownAndValid = false;
// Checks that the borders does not contain NaN as longitudes and latitudes
if (!Double.isNaN(NE.getLatitude())
&& !Double.isNaN(NE.getLongitude())
&& !Double.isNaN(SW.getLatitude())
&& !Double.isNaN(SW.getLongitude())) {
// The borders can be used
bordersKnownAndValid = true;
}
if (bordersKnownAndValid) {
ArrayList<Report> localReports = (ArrayList<Report>) (Report.getReportsWithinBoundingBounds(NE, SW, selectedCategoryIdToBeShownOnMap).get(1));
// Revalidate only if we have something new to show
if (localReports.size() > 0) {
currentMap.clearMapLayers();
currentMap.addMarker(ParametresGeneraux.getCurrentUser().getUserIcon(),
new Coord(ParametresGeneraux.getCurrentUser().getCurrentUserLocation().getLatitude(),
ParametresGeneraux.getCurrentUser().getCurrentUserLocation().getLongitude()),
ParametresGeneraux.getCurrentUser().getUserNickname(), "", null);
Image tempPlaceholder = Image.createImage(
reportImageWidth,
reportImageWidth,
ParametresGeneraux.accentColor);
Graphics gr = tempPlaceholder.getGraphics();
gr.setAntiAliased(true);
gr.setColor(ParametresGeneraux.accentColor);
gr.fillArc(0, 0, reportImageWidth, reportImageWidth, 0, 360);
EncodedImage roundPlaceholder = EncodedImage.createFromImage(tempPlaceholder, true);
// Add the report on the map
for (Report report : localReports) {
String photoFilenameInStorage = Report.getFilename(report.getPhotoPath())
+ ParametresGeneraux.SUFFIX_ON_MAP_IMAGE;
EncodedImage reportIcon = EncodedImage.createFromImage(URLImage.createToStorage(roundPlaceholder,
photoFilenameInStorage,
report.getPhotoPath(),
ParametresGeneraux.RESIZE_SCALE_WITH_ROUND_MASK
),
false); // we want transparency png otherwise it shows black edges
currentMap.addMarker(reportIcon,
new Coord(report.getLocation().getLatitude(), report.getLocation().getLongitude()
),
report.getCategory().getName(), "",
(evt) -> {
// Opens the detail form about this report
new ReportDetailsForm(theme, report, f.getClass()).show();
});
}
currentMap.setCameraPosition(new Coord(center.getLatitude(), center.getLongitude()));
currentMap.zoom(new Coord(center.getLatitude(),
center.getLongitude()),
ParametresGeneraux.getUserZoomLevelOnMap());
currentMap.animate();
//f.forceRevalidate();
}
}
}
So I guess that the flickering in the simulator is a kind of slow motion of what happens on the device although the device does not show the placeholder.
What should I do to make the markers appear with an image?
EDIT March 8th 2017
On simulator, if I show a Dialog just before adding the marker to the map with this code :
Dialog.show("Photo", report.getAddress(), Dialog.TYPE_INFO, reportIcon, "OK", null);
The icon is well displayed in the Dialog (see screen capture below)
and then the image appears on the map without flickering any more as depicted below :
However on an actual Android device even the Dialog does not appear.
Finally I don't know why the Dialog makes then the markers behave as expected on the simulator but not on the device, so I am a bit at lost!
Any help would be precious.

The problem is that URLImage may not have finished downloading by the time you added it as a marker. If you call EncodedImage.createFromImage(urlImage) before URLImage has finished downloading, then you'll be creating an encoded image of the urlImage's placeholder.
the com.codename1.io.Util class includes quite a few methods for downloading images from URLs. Some are blocking, and some use a callback. Either way you just need to ensure that the image is actually downloaded before adding it to a map.
NOTE: Normally this wouldn't be an issue with URLImage - e.g. if you were adding it to a Button or a Label. It is only a problem here because the MapContainer is native, and it actually needs to pass the image data to the native layer at the time that setMarker() is called.

Related

Google Map Lite Mode moveCamera does not call setOnCameraIdleListener

Map shows correctly, then I check that the map is fully loaded before I do the moveCamera on it. The map then shows the correct area as defined by the bounds. But after the move, the setOnCameraIdleListener is never called as is expected. Here is the bit of code of question
map.setOnMapLoadedCallback(GoogleMap.OnMapLoadedCallback {
Log.e(tag, "setOnMapLoadedCallback")
//set camera bounds
map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100))
})
map.setOnCameraIdleListener {
//create snapshot
Log.e(tag, "setOnCameraIdleListener")
}
I am using lite mode for the map and according to the documentation it looks like it should be supported but I couldn't find anything definite.
What may I be missing?
UPDATE:
Here is how I worked around this bug in the SDK.
Created a val defined as the callback.
private val snapshotReadyCallback : GoogleMap.SnapshotReadyCallback = GoogleMap.SnapshotReadyCallback {
SaveSnapshot(it)
}
"it" is a bitmap of the map. You could do the saving directly in the callback but I call a function instead.
Within setOnMapLoadedCallback did the following
gmap?.setOnMapLoadedCallback {
gmap?.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100))
//2 seconds lag to ensure camera has had time to move
//since camera move override doesnt work in setOnMapLoadedCallback
handler.postDelayed({ // Do something after 2s = 2000ms
gmap?.snapshot(snapshotReadyCallback)
}, 2000)
}
Adding the delay to grab the snapshot allowed enough time for the camera to have moved already. It will then call the snapshotReadyCallback which will then call a function that does the actual saving.

InfoBox is empty

My Cesium infobox is empty after I dynamically select an element.
This is how I'm selecting the element.
public selectById(id: string): void {
console.log('selecting ' + id);
if (id != null) {
// this.viewer is Cesium.Viewer => https://cesiumjs.org/Cesium/Build/Documentation/Viewer.html?classFilter=viewer
this.viewer.selectedEntity = this.viewer.entities.getById(id);
// viewer.flyTo messes up the camera pitch
this.viewer.camera.flyTo({destination: this.viewer.selectedEntity.position.getValue(Cesium.JulianDate.now())});
}
}
The entity is selected, the camera flys to it just fine, and the Cesium infobox displays the entity name in the title just fine, but doesn't display the description. If I select the entity by clicking on it, the box displays the description just fine.
I can't find anything to force the InfoBox to redraw, or see anything else I need to set for the InfoBox to update. So what am I missing?
I tried setting this.viewer.infoBox.viewModel.description but that didn't help either.
Apparently this was caused by selecting the entity while the map container was set to display: none. I was able to fix this by delaying the execution until focus returned to the map.

(Maps) Avoid camera to comeback to prior position when I add a new Pin

I have an app that shows a Map and a Pin on the center of it(just like Uber and PedidosYa), I have a button that when I click it sends the location where the pin's on. And it makes to appear the closest stores around that pin.
My problem is that when the first time the map appears its centered in my location, I move the map around to locate the pin, and when I click the button I want the map to stay there, but its comeback to the prior location and THEN moves the camera to the location where I drop the pin. I want to avoid that moving.
The function I use when I click the button to drop the pin is something like this:
var CenterPos = customMap.GetMapCenterLocation();
var pinPersonal = new CustomPin()
{
Id = "000",
Position = new Position(CenterPos.Latitude, CenterPos.Longitude),
Label = "Mio",
Url = "Mío"
};
customMap.Pins.Add(pinPersonal);
This draws a pin where I click the button. If I keep it this way, it draws the pin, and the camera comesback to the prior location.
After I use something like this:
customMap.MoveToRegion(MapSpan.FromCenterAndRadius(
new Position(latitud, longitud), Distance.FromMiles(0.2)));
that makes the camera to move to the location I choose. But it comebacks always to the prior location and the moves to the new one.
Any idea? Im not sure from where this behavior comes.
Did you implement CustomMap according with Customizing a Map Pin - Xamarin?
Probably you should override OnMarkerClickListener.OnMarkerClick and return true in your custom renderer.
This means disable default behavior(centering map, open info-window) and you can implement your own behavior when pin clicked.
See this link.
Markers  |  Maps SDK for Android  |  Google Developers
/** Called when the user clicks a marker. */
#Override
public boolean onMarkerClick(final Marker marker) {
// Retrieve the data from the marker.
Integer clickCount = (Integer) marker.getTag();
// Check if a click count was set, then display the click count.
if (clickCount != null) {
clickCount = clickCount + 1;
marker.setTag(clickCount);
Toast.makeText(this,
marker.getTitle() +
" has been clicked " + clickCount + " times.",
Toast.LENGTH_SHORT).show();
}
// Return false to indicate that we have not consumed the event and that we wish
// for the default behavior to occur (which is for the camera to move such that the
// marker is centered and for the marker's info window to open, if it has one).
return false;
}

Highcharts not zooming series using option Highcharts.Series.prototype.drawPoints = function() { }

I am creating a graph where I want to show the markers of the series only when hovering. I already tried the solution as shown on this question (Highcharts markers on legend and hover ONLY), and it works perfectly to show the markers when I want to.
However, I have another graph in the same html page that needs to show the markers and when I applied the solution presented on that question on the graph that I want (first graph) and I zoom at the other graph (second graph) the series that are represented by dots does not zoom, they keep all the markers on the graph.
The option
Highcharts.Series.prototype.drawPoints = function() { };
is on line 37 of the jsfiddle https://jsfiddle.net/erifel/sx3dcmny/
You should be able to use marker.enabled: false and series.states.hover.lineWidthPlus: 0 for achieving your chart without reseting drawPoints function. This will give you a possibility to redraw your markers when zooming on you chart.
If you want to show hidden markers in your legend, you can wrap renderItem function in your Legend prototype:
H.wrap(H.Legend.prototype,'renderItem',function(proceed,item){
var enabled = item.options.marker.enabled;
item.options.marker.enabled = true;
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
item.options.marker.enabled = enabled;
});
Here you can see an example how it can work: https://jsfiddle.net/sx3dcmny/12/

Programmatically zooming the AudioVideoCaptureDevice?

Anybody know how to programmatically zoom the AudioVideoCaptureDevice in Windows Phone 8?
I am using AudioVideoCaptureDevice (and yes, I want that specific device so I can control the VideoTorchMode property). I can't for the life of me figure out the zooming though. I am painting a Canvas using a VideoBrush mapped to the AudioVideoCaptureDevice. I'd like to implement Pinch-Zoom or even a simple +/- button to Zoom the camera.
What am I missing?
I'm not familiar with any API in WP8 that would allow you to programmetically set the zoom on a PhotoCaptureDevice/AudioVideoCaptureDevice. My theory is that you can do it manually by implementing your own Pinch-to-zoom functionality and making sure that region is focused.
For information on how to Focus on a region using WP8 Camera APIs see Nokia's Camera Explorer. The core of what you're looking for can be found on this architectural guide under "tap-to-focus".
private async void videoCanvas_Tap(object sender, GestureEventArgs e)
{
System.Windows.Point uiTapPoint = e.GetPosition(VideoCanvas);
if (_focusSemaphore.WaitOne(0))
{
// Get tap coordinates as a foundation point
Windows.Foundation.Point tapPoint = new Windows.Foundation.Point(uiTapPoint.X, uiTapPoint.Y);
double xRatio = VideoCanvas.ActualWidth / _dataContext.Device.PreviewResolution.Width;
double yRatio = VideoCanvas.ActualHeight / _dataContext.Device.PreviewResolution.Height;
// adjust to center focus on the tap point
Windows.Foundation.Point displayOrigin = new Windows.Foundation.Point(
tapPoint.X - _focusRegionSize.Width / 2,
tapPoint.Y - _focusRegionSize.Height / 2);
// adjust for resolution difference between preview image and the canvas
Windows.Foundation.Point viewFinderOrigin = new Windows.Foundation.Point(displayOrigin.X / xRatio, displayOrigin.Y / yRatio);
Windows.Foundation.Rect focusrect = new Windows.Foundation.Rect(viewFinderOrigin, _focusRegionSize);
// clip to preview resolution
Windows.Foundation.Rect viewPortRect = new Windows.Foundation.Rect(0, 0, _dataContext.Device.PreviewResolution.Width, _dataContext.Device.PreviewResolution.Height);
focusrect.Intersect(viewPortRect);
_dataContext.Device.FocusRegion = focusrect;
// show a focus indicator
FocusIndicator.SetValue(Shape.StrokeProperty, _notFocusedBrush);
FocusIndicator.SetValue(Canvas.LeftProperty, uiTapPoint.X - _focusRegionSize.Width / 2);
FocusIndicator.SetValue(Canvas.TopProperty, uiTapPoint.Y - _focusRegionSize.Height / 2);
FocusIndicator.SetValue(Canvas.VisibilityProperty, Visibility.Visible);
CameraFocusStatus status = await _dataContext.Device.FocusAsync();
if (status == CameraFocusStatus.Locked)
{
FocusIndicator.SetValue(Shape.StrokeProperty, _focusedBrush);
_manuallyFocused = true;
_dataContext.Device.SetProperty(KnownCameraPhotoProperties.LockedAutoFocusParameters,
AutoFocusParameters.Exposure & AutoFocusParameters.Focus & AutoFocusParameters.WhiteBalance);
}
else
{
_manuallyFocused = false;
_dataContext.Device.SetProperty(KnownCameraPhotoProperties.LockedAutoFocusParameters, AutoFocusParameters.None);
}
_focusSemaphore.Release();
}
}
Here's how to implement your own pinch-to-zoom functionality in WP8 # Pinch To Zoom functionality in windows phone 8
One thing I'd add to the pinch-to-zoom code sample in your case is a Clip specification on a parent control to make sure you're not accidentally rendering images tens or hundreds of times bigger then the screen and killing your app's performance.