Offline geocoding with MMPK locator

980
7
Jump to solution
03-20-2023 11:15 AM
smithse
New Contributor III

Hi all,

I am new to Qt and QML though I have experience in .Net. I am using the samples provided in the appstudio to create an offline mobile app that will permit searching and eventually routing.

I am stuck at trying to be able to search/find a POI using a locator which I have authored and packaged to an MMPK. I can load and view the contents just fine but geocoding based on the example is just not working.

 

It would appear that I cannot bind my search (text) field to the locator suggestions searchText

Does anyone have an example of offline geocoding using an MMPK locator?

I found that the sample works with mods to the url property but I do have to unpack the package, and set the url to the .loc file.

0 Kudos
1 Solution

Accepted Solutions
smithse
New Contributor III

Hey Tanner,

So, I found that doesn't work, but this does:

                        onTextChanged: {
                            console.log("Text changed: " + findText);
                            //currentLocatorTask.suggestions.suggestParameters.maxResults = 50; //errors out (TypeError: Value is null and could not be converted to an object

                            var suggestParams = ArcGISRuntimeEnvironment.createObject("SuggestParameters");
                            suggestParams.maxResults = 15;

                            currentLocatorTask.suggestions.suggestParameters = suggestParams;
                            currentLocatorTask.suggestions.searchText = findText;
                        }


Thanks again for your responses!

View solution in original post

7 Replies
Tanner_Yould
Esri Contributor

Hi Smithse, hopefully I can be of some help. It looks like your workflow of connecting to the LocatorTask's url property to the .loc file is correct, but you can also get a LocatorTask property from a loaded MobileMapPackage. If you'd like to avoid having to unpack or load an MMPK, you can also create a .loc file directly from ArcGIS Pro with the Create a locator geoprocessing tool.

If you'd like additional code to reference, you can take a look an another Offline Geocode sample in our Qt samples repo. That makes use of a .loc file for San Diego that you can test your code with.

Let me know if that helps, and I'm happy to provide any other assistance if necessary!

Tanner Yould
Samples Product Engineer
ArcGIS Maps SDK for Qt
Esri
smithse
New Contributor III

Hi Tanner,

Thanks for the response. That sample was very helpful in getting my first bit of code working, and is what I derive my working code from currently. For the life of me however, I cannot seem to be able to bind and get suggestions from the LocatorTask property of the loaded MMPK.

My hacked together code currently consists of loading the map from the MMPK, and using the .loc from the same package, after is is unpacked. I guess I am essentially duplicating the data and just looking for a way to avoid this.

Cheers,
Sean

0 Kudos
Tanner_Yould
Esri Contributor

Hm, if I understand correctly, you're able to get the locator task from your loaded MMPK but unable to retrieve any LocatorTask.suggestions when you create it that way. But you're able to get the suggestions when you create a LocatorTask component with a .loc file. I hope I have that correct.

Without seeing your code, I'm wondering if your LocatorTask is being instantiated correctly from the MMPK. It can be a little odd, so you might want to check out our MobileMap_SearchAndRoute sample, where we get a LocatorTask from an MMPK rather than creating a component with a URL or path to a .loc file. Is there any possibility you can share some of your code? Alternatively, is there a way you can check if there are load errors or geocode errors? You can check with the following code block:

 

 

Connections {
    target: locatorTask // the name of your locator task property

    function onLoadErrorChanged() {
        // Catch any errors when loading the task
        console.log(locatorTask.loadError.message, locatorTask.loadError.additionalMessage);
    }
    
    function onGeocodeStatusChanged() {
        // Catch any errors in the geocode process
        if (locatorTask.geocodeStatus === Enums.TaskStatusErrored) {
            console.log(locatorTask.error.message, locatorTask.error.additionalMessage);
        }
    }
    
    function onErrorChanged() {
        // Catch any other general errors
        console.log(locatorTask.error.message, locatorTask.error.additionalMessage);
    }
}

 

 

Thank you, I hope that helps, and sorry for the trouble!

Tanner Yould
Samples Product Engineer
ArcGIS Maps SDK for Qt
Esri
0 Kudos
smithse
New Contributor III

Hi again, Tanner,

Thanks for the response and please, no apologies needed! 😀

Below is some of the code: it's ugly as it's been chopped down to try and resolve this suggestions issue. When I get the LocatorTask from the MMPK, I don't seem to be able to set the suggestions.searchText property. Maybe this is what I am doing wrong and is the issue (here's hoping!)

The code you provided closely matches mine, with the exception of the onErrorChanged() function, so I will play around with that and see if anything shows up. In the meantime, here's bits of what I have... and this all works fine. It would just be nice to not have to use two LocatorTask(s).

    

//MapView - when map changes, instantiate a locator
//This code has been made as short as possible as I am not looping though files and folders. We simply load the map and use (try to) the locator from the package
onMapChanged: {
        mapView.resetMap();

        // change the locatorTask: messed around here making sure it loaded
        mmpk.locatorTask.objectType === "LocatorTask" ? mapLocatorTask = mmpk.locatorTask: mapLocatorTask = null
       
        // determine if map supports routing
        if (mapView.map.transportationNetworks.length > 0) {
            currentRouteTask = ArcGISRuntimeEnvironment.createObject("RouteTask", {transportationNetworkDataset: mapView.map.transportationNetworks[0]});
            currentRouteTask.load();
        }

        else {
            currentRouteTask = null;
        }
    }


    //------------------BEGIN MobileMapPackage -------------------
    property string packageName: "QuikMap"
    property string sharedDataPath: AppFramework.resolvedPathUrl(
                                        AppFramework.userHomeFolder.filePath("ArcGIS/AppStudio/Data/")) + "/";

    property string packageFileNameWithPath: sharedDataPath + packageName + ".mmpk"

    MobileMapPackage {
        id: mmpk
        path: packageFileNameWithPath

        onLoadStatusChanged: {
            if (loadStatus !== Enums.LoadStatusLoaded)
                return;

            mapView.map = mmpk.maps[0];

            //Todo: some checks here about the mmpk that is being loaded

//Note: have also tried to instantiate the mapLocatorTask from here...

        }

        Component.onCompleted: {
            mmpk.load();
        }
    }
    //------------------END MobileMapPackage -------------------






//This is the locator task that works when pointing to a .loc
LocatorTask {
    id: locatorTask
    url:  locatorUrl //path to the .loc from the unpacked mmpk
    suggestions.suggestParameters: SuggestParameters{
        maxResults: 50
        preferredSearchLocation: currentViewPointCentre
    }
    suggestions.searchText: searchTextField.text
    onGeocodeStatusChanged: {
        if (geocodeStatus === Enums.TaskStatusCompleted) {
            if(geocodeResults.length>0){
                //code ommitted for clarity
            }
        }
    }
}








Cheers again,
Sean

0 Kudos
smithse
New Contributor III

So... I think I have one of the errors of my ways 🙂

With the LocatorTask declared (as in the bottom of the snippet above) and the suggestions.searchText bound to the TextField, a change to that textfield caused the suggestions to be generated.

When the LocatorTask in the mmpk is used, the suggestions do not get returned.

What I have done now, is explicitly call or should I rather say, set, the property when the value of the text field changes, like this:

mmpk.locatorTask.suggestions.searchText = searchText; 

This does return suggestions, but only 5 and I cannot see how to change the maxResults parameter when the locator is pointing to the package LocatorTask.

Any suggestions? <- no pun intended 🤣

Once I get this working, I will post a complete snippet as it may help someone else in the future.

 

 

 

0 Kudos
Tanner_Yould
Esri Contributor

Are you able to update the SuggestParameters.maxResult property? That would look like this: 
`mmpk.locatorTask.suggestions.suggestParameters.maxResults = 10; // or some number`.

Tanner Yould
Samples Product Engineer
ArcGIS Maps SDK for Qt
Esri
0 Kudos
smithse
New Contributor III

Hey Tanner,

So, I found that doesn't work, but this does:

                        onTextChanged: {
                            console.log("Text changed: " + findText);
                            //currentLocatorTask.suggestions.suggestParameters.maxResults = 50; //errors out (TypeError: Value is null and could not be converted to an object

                            var suggestParams = ArcGISRuntimeEnvironment.createObject("SuggestParameters");
                            suggestParams.maxResults = 15;

                            currentLocatorTask.suggestions.suggestParameters = suggestParams;
                            currentLocatorTask.suggestions.searchText = findText;
                        }


Thanks again for your responses!