HelloWorld
HelloWorld

Reputation: 2355

URLImage on MapContainer not displayed on actual device and flickering in simulator

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.

Markers with only the placeholder shown (user avatar's icon is further down)

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)

The Dialog shows the image

and then the image appears on the map without flickering any more as depicted below :

Afterwards the image remains on the map

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.

Upvotes: 1

Views: 78

Answers (1)

steve hannah
steve hannah

Reputation: 4716

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.

Upvotes: 1

Related Questions