Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App freezes when loading KML layer #582

Closed
sharkboy777 opened this issue Nov 15, 2019 · 28 comments
Closed

App freezes when loading KML layer #582

sharkboy777 opened this issue Nov 15, 2019 · 28 comments
Labels
stale status: blocked Resolving the issue is dependent on other work.

Comments

@sharkboy777
Copy link

sharkboy777 commented Nov 15, 2019

I am trying to add KML layer on to the maps. It was working okay with just a ms of freeze when i try to load the small size KML file. But some files are large with size more than 1Mb - 10Mb.. in these all cases app is getting frozen for some time while the layer is adding to the map.

Below is the Asynctask class i am using to read the kml file from local storage path and adding it to maps.

I tried this in many ways using handlers, threads, asynctasks... as i cannot update the UI in background thread... this is causing my app to freeze for some time.

Eventhough it freezes I wouldn't mind but in some device while the app is frozen if the user interacts with the app then app is getting crashed. In some devices it is displaying "wait" dialog.

Please help me out.

`
private static class AddKMLLayerToMaps extends AsyncTask<String, String, KmlLayer> {

    //added weakreference to avoid memory leaks
    private WeakReference<CoverageFragment> weakReferencedFragment;

    AddKMLLayerToMaps(CoverageFragment reference) {

        this.weakReferencedFragment = new WeakReference<>(reference);

        weakReferencedFragment.get().showLoading();
    }

    @Override
    protected KmlLayer doInBackground(String... strings) {

        try {

            TraceUtils.logE("Coverage kml Path", strings[0]);

            FileInputStream fileInputStream = new FileInputStream(strings[0]);

            CoverageFragment fragment = weakReferencedFragment.get();
            if (fragment == null || fragment.getActivity() == null || fragment.getActivity().isFinishing()) {
                return null;
            }

            KmlLayer kmlLayer = new KmlLayer(fragment.mMap, fileInputStream, getApplicationContext());

            fileInputStream.close();

            File file = new File(strings[0]);
            if (file.exists()) file.delete();

            return kmlLayer;

        } catch (Exception e) {

            weakReferencedFragment.get().hideLoading();

            TraceUtils.logException(e);

        }

        return null;
    }

    @Override
    protected void onPostExecute(KmlLayer kmlLayer) {

        super.onPostExecute(kmlLayer);

        if (kmlLayer != null) {

            //add the KML layer to map using the UI thread
            weakReferencedFragment.get().mActivity.runOnUiThread(() -> {
                try {

                    kmlLayer.addLayerToMap();

                } catch (Exception e) {

                    weakReferencedFragment.get().hideLoading();

                    TraceUtils.logException(e);

                }
            });

            //zoom to the center of KML layer containers
            new MoveMapToKMLLayer(weakReferencedFragment.get()).execute(kmlLayer);
        }
    }

}`
@sharkboy777 sharkboy777 added triage me I really want to be triaged. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. labels Nov 15, 2019
@barbeau
Copy link
Collaborator

barbeau commented Nov 21, 2019

@sharkboy777 Could you please provide a sample KML file that you're having this problem with?

@barbeau barbeau added needs more info This issue needs more information from the customer to proceed. and removed triage me I really want to be triaged. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. labels Nov 21, 2019
@sharkboy777
Copy link
Author

@sharkboy777 Could you please provide a sample KML file that you're having this problem with?
https://drive.google.com/file/d/1sbNgwgLqdmKbJR3nnOxpp4ZTSa7DWRFl/view?usp=sharing

Here is the drive link for kml file... please give me a solution

@barbeau barbeau added triage me I really want to be triaged. and removed needs more info This issue needs more information from the customer to proceed. labels Nov 22, 2019
@sharkboy777
Copy link
Author

@sharkboy777 Could you please provide a sample KML file that you're having this problem with?
https://drive.google.com/file/d/1sbNgwgLqdmKbJR3nnOxpp4ZTSa7DWRFl/view?usp=sharing

Here is the drive link for kml file... please give me a solution

any update on this??

@sharkboy777
Copy link
Author

sharkboy777 commented Dec 16, 2019

Got anything on this issue?? Or atleast before adding the kml layer onto the maps, is it possible to get renderer object, to parse the KML data and get the polygons?

Why because, right now it seems to be not possible to get the renderer object before adding the KML layer onto maps.

@barbeau
Copy link
Collaborator

barbeau commented Dec 16, 2019

@sharkboy777 I haven't had time to look at this

@jeffdgr8
Copy link
Contributor

I CPU profiled loading this KML and the bottleneck is calling GoogleMap.addPolygon(). It calls the method 9377 times, since there's so many polygons in the 20 KMLs embedded in this single KML. Google Maps on the web won't even load KMLs over 5MB, so I couldn't compare the performance there. Google Earth does do a good job loading and displaying this KML in a web browser fairly quickly though. Any performance optimization for loading this KML on Android would have to be done in the GoogleMap addPolygon() method, which isn't part of the android-maps-utils library.

I'd suggest splitting this KML into 20 smaller KMLs that can be loaded and displayed individually. Even if you display them all at once, you could at least add them to the map on separate main thread run loops to avoid freezing the UI for as long.

@sharkboy777
Copy link
Author

sharkboy777 commented Jan 27, 2020

I CPU profiled loading this KML and the bottleneck is calling GoogleMap.addPolygon(). It calls the method 9377 times, since there's so many polygons in the 20 KMLs embedded in this single KML. Google Maps on the web won't even load KMLs over 5MB, so I couldn't compare the performance there. Google Earth does do a good job loading and displaying this KML in a web browser fairly quickly though. Any performance optimization for loading this KML on Android would have to be done in the GoogleMap addPolygon() method, which isn't part of the android-maps-utils library.

I'd suggest splitting this KML into 20 smaller KMLs that can be loaded and displayed individually. Even if you display them all at once, you could at least add them to the map on separate main thread run loops to avoid freezing the UI for as long.

afdfd

I CPU profiled loading this KML and the bottleneck is calling GoogleMap.addPolygon(). It calls the method 9377 times, since there's so many polygons in the 20 KMLs embedded in this single KML. Google Maps on the web won't even load KMLs over 5MB, so I couldn't compare the performance there. Google Earth does do a good job loading and displaying this KML in a web browser fairly quickly though. Any performance optimization for loading this KML on Android would have to be done in the GoogleMap addPolygon() method, which isn't part of the android-maps-utils library.

I'd suggest splitting this KML into 20 smaller KMLs that can be loaded and displayed individually. Even if you display them all at once, you could at least add them to the map on separate main thread run loops to avoid freezing the UI for as long.

  • The problem here is that, I can't even access the KML Layer object without rendering it on the map first(which already takes an ample amount of time). If I could do that then it will be easier for me to retrieve the polygons from each kml file and draw them on map without rendering the entire kml file on maps

  • There is no way for me to get 20 kml files instead of single kml file from the server. I will receive these single KML files(with more kmls in it) like above

  • Is there any way to get the KMLLayer or KMLRenderer object without actually rendering it on the maps first?

@jeffdgr8
Copy link
Contributor

KmlLayer is created before calling addLayerToMap(), which adds the polygons to the map. Constructing KmlLayer is also fairly long-running, as it takes a good amount of I/O and processing to parse such a large KML. Constructing the KmlLayer can be done on a background thread though, avoiding blocking the UI. But addLayerToMap() has to be called on the main thread, which is why it causes freezing to add such a large KML to the map.

If you're unable to edit the KML and break it up into multiple smaller files, I'd suggest still making sure you at least are constructing the KmlLayer on a background thread. addLayerToMap() has to be done on the main thread though.

For reference, I updated the KmlDemoActivity to construct the KmlLayer in the background in #607.

@jeffdgr8
Copy link
Contributor

CPU profiling identifies GoogleMap.addPolygon() as the bottleneck adding KmlLayer to the map. Within this method, the bottleneck is ArrayList.sort(), called in a couple places by Collections.sort().

The long-running KmlLayer.<init> can all be done on a background thread. But the KmlLayer.addToMap() has to be done on the main thread.

Screenshot 2020-01-27 at 5 54 00 PM

@jpoehnelt @arriolac hard to know exactly what could be optimized in the closed-source GoogleMap code, but the GoogleMap.addPolygon() method could likely be optimized significantly by utilizing a collection type that provides more efficient sorting or if somehow that sorting could be limited, avoided, or done off of the main thread.

@barbeau
Copy link
Collaborator

barbeau commented Jan 28, 2020

@jeffdgr8 Have you tried profiling the library with the Android Maps v3 beta SDK? https://github.com/googlemaps/android-maps-utils/commits/android-sdk-v3-beta

We have a similar bottleneck for clustering when adding markers with Maps API v2, and slow performance adding markers was called out as fixed in the Android v3 beta SDK - see #164 (comment). Not sure if this fix also addresses slow performance adding polygons, but 🤞 if it was just a simple Collection sorting issue.

@barbeau barbeau added status: blocked Resolving the issue is dependent on other work. and removed triage me I really want to be triaged. labels Jan 28, 2020
@jeffdgr8
Copy link
Contributor

@barbeau I actually did pull the maps v3 branch to test and ran into this crash again on my Pixel Slate. I'll try profiling again on my phone. I also wanted to merge master into the android-sdk-v3-beta branch, which has conflicts.

I was happy to see that performance issue fixed in v3, as I was tracking it closely. There hasn't been much movement on the v3 beta since it was first announced last spring, not even an iterative beta release with that crash fixed.

@jeffdgr8
Copy link
Contributor

jeffdgr8 commented Jan 28, 2020

I profiled with the maps v3 beta (#608) and actually couldn't get the KML to display on the map at all. The app hung for a few minutes with the main thread blocked and eventually crashed.

2020-01-28 15:45:03.596 13775-13816/com.google.maps.android.utils.demo E/System: java.lang.OutOfMemoryError: OutOfMemoryError thrown while trying to throw an exception; no stack trace available
2020-01-28 15:44:31.912 589-589/? A/libc: crash_dump helper failed to exec
2020-01-28 15:45:04.379 13775-13882/? E/AndroidRuntime: Error reporting crash
    java.lang.OutOfMemoryError: OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack trace available

Other smaller KML files worked as expected.

@barbeau
Copy link
Collaborator

barbeau commented Jan 28, 2020

@jeffdgr8 Thanks for checking that out. So is that actually a regression from Maps SDK v2? Would Maps SDK v2 eventually load if you gave it enough time?

@jeffdgr8
Copy link
Contributor

@barbeau yes, with the v2 SDK it takes 10-15 seconds to add the polygons and display on the map. So this is a regression in v3. I created a bug report.

@sharkboy777
Copy link
Author

KmlLayer is created before calling addLayerToMap(), which adds the polygons to the map. Constructing KmlLayer is also fairly long-running, as it takes a good amount of I/O and processing to parse such a large KML. Constructing the KmlLayer can be done on a background thread though, avoiding blocking the UI. But addLayerToMap() has to be called on the main thread, which is why it causes freezing to add such a large KML to the map.

If you're unable to edit the KML and break it up into multiple smaller files, I'd suggest still making sure you at least are constructing the KmlLayer on a background thread. addLayerToMap() has to be done on the main thread though.

For reference, I updated the KmlDemoActivity to construct the KmlLayer in the background in #607.

yes.. for now i am getting the kmllayer object on a background thread and then adding the layertomap using main ui thread.

There is another issue in this same kml file, which is it doesn't load the styles but just loads the plain black polygon lines without any fill colors. Raised this issue in the below ticket.
https://github.com/googlemaps/android-maps-utils/issues/583

Because of the above issue, I had to get all polygon objects from the rendered kmllayer and draw them on maps again using polygon styles to get the output. I don't know exactly if it is the issue with map-utils library or the kml file itself

@sharkboy777
Copy link
Author

@barbeau yes, with the v2 SDK it takes 10-15 seconds to add the polygons and display on the map. So this is a regression in v3. I created a bug report.

@jeffdgr8 , @barbeau Thank you guys for helping out with the issue and reporting it to google. Hope they fix it soon😊😊

@stale
Copy link

stale bot commented May 29, 2020

This issue has been automatically marked as stale because it has not had recent activity. Please comment here if it is still valid so that we can reprioritize. Thank you!

@stale stale bot added the stale label May 29, 2020
@arriolac
Copy link
Member

Not stale.

@arriolac arriolac removed the stale label Jul 15, 2020
@stale
Copy link

stale bot commented Nov 13, 2020

This issue has been automatically marked as stale because it has not had recent activity. Please comment here if it is still valid so that we can reprioritize. Thank you!

@stale stale bot added the stale label Nov 13, 2020
@barbeau
Copy link
Collaborator

barbeau commented Nov 13, 2020

Not stale.

@stale stale bot removed the stale label Nov 13, 2020
@stale
Copy link

stale bot commented Mar 19, 2021

This issue has been automatically marked as stale because it has not had recent activity. Please comment here if it is still valid so that we can reprioritize. Thank you!

@stale stale bot added the stale label Mar 19, 2021
@jeffdgr8
Copy link
Contributor

Not stale

@stale stale bot removed the stale label Mar 20, 2021
@obete
Copy link

obete commented May 15, 2021

Still useful

@stale
Copy link

stale bot commented Sep 19, 2021

This issue has been automatically marked as stale because it has not had recent activity. Please comment here if it is still valid so that we can reprioritize. Thank you!

@stale stale bot added the stale label Sep 19, 2021
@jeffdgr8
Copy link
Contributor

Not stale

@stale stale bot removed the stale label Sep 19, 2021
@stale
Copy link

stale bot commented Apr 16, 2022

This issue has been automatically marked as stale because it has not had recent activity. Please comment here if it is still valid so that we can reprioritize. Thank you!

@stale stale bot added the stale label Apr 16, 2022
@stale
Copy link

stale bot commented Nov 2, 2022

Closing this. Please reopen if you believe it should be addressed. Thank you for your contribution.

@stale stale bot closed this as completed Nov 2, 2022
@mohsin-ka
Copy link

Not Stale, Still m facing this issue with latest sdk in 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale status: blocked Resolving the issue is dependent on other work.
Projects
None yet
Development

No branches or pull requests

6 participants