facebook-squared twitter-squared rss-squared gplus-squared

Saturday

10

February 2018

2

COMMENTS

Let Geo location work on Hybrid Mobile Apps

Written by on 10 February 2018

resolve geo location ionic cordova

I’ll focus on Geo location with Ionic framework but same is true for others (All of them that use cordova/phonegap in one way or the other such as nativscript, weex, quasar).

By Hybrid mobile apps I mean apps that uses web technologies and cordova to run native on handheld devices.

Using a native feature in Ionic is a two step process.
1. Install a cordova plugin
2. Install ionic wrapper

Developing an Ionic application is a breeze because they are easy to debug and test. Because they use web technogies so you can debug them like rest of your web apps using browser developer tools. Unlike nativescript which requires an emulator. The second line adds a wrapper which converts cordova plugin into a Promise. It also handle errors if app runs in non cordova based environment i-e browser.

Lets get user current coordinates.

this.geo.getCurrentPosition({timeout: 30000})
.then(location => {
  console.log(location.coords)
  //latitude:12.34567
  //longitude:01.01010
}.catch(error => {
  console.log(error)
}

Whenever an app encounters this code, it asks user to authorize the Geo location access as shown in following screenshot.

Request for Geo location authorization Ionic

If user allows Geo location access, code runs in then block. We get user’s current position, end of story. The catch block kicks in when user denies.

That’s all I have for you today. If you don’t want to go beyond happy case that leave right now.

But…..

Look at this thread. Here people are giving reference of increasing timeout to 60 seconds to get over this problem. But there is no winning reply to this thread because they are missing a very basic concept.

The above code snippet will sometimes return nothing. Both then and catch blocks can beskipped. Giving geo location access is useless if location is disabled from settings. That’s why there is {timeout:30000} which waits for thirty seconds. It’s like detecting the inbound aircraft when your radars are turned off.

That’s the whole purpose and motivation behind this article.

Enough with Diagnosing

Let’s come to the solution. To best explain things, I have created the following flow diagram. (click on the image for larger version and watch out all those cross references)

Resolve Geolocation cordova ionic

In steps it would be
1. Check Location permission
2. If app is authorized than check whether location setting is enabled
3. If location enabled true than you are set to go
4. From Step 1, if location is not authorized than requestLocationAuthorization
5. If it’s granted than we check whether location setting is enabled
6. If not than requestEnableLocation
7. As soon as user Agrees, we have fully working Geo location.

Solution

We need plugins such as Diagnostic and Request Location Accuracy Plugin. The latter one requests enabling/changing of Location Services by triggering a native dialog from within the app, avoiding the need for the user to leave your app to change location settings manually.

Request Location Services using native dialog ionic

Request location services using native dialog

There are many ways to achieve via code whatever mentioned in the chart above. I tried go the linear way like mentioned in the steps but there we some many if/else block and callback and all the cross referencing.

In order to better deal this async behavior I am gonna use async/await. Location is prerequisite in my case, otherwise app will not be usable.

private async detectGeolocation() {
  const locAuthorized = await this.diagnostic.isLocationAuthorized();
  const locAvailable = await this.diagnostic.isLocationAvailable();

  if (locAuthorized && locAvailable) {

    // You location is authorized you are good to go :)
    this.initApp();
  } else {
    // Looks like you have no access to GPS, you need to resolve Geo Location :(
  }
}

On line 2 and 3 I am using Ionic Native wrapper for cordova diagnostic plugin which converts it into nice Promise. Both of these two lines will return boolean which will stored in their associated variables. On Line 5 I am deciding whether to allow app usage ask user to resolve Geo location.

public async resolveGeolocation() {
  try {
    const reqLocAuthorization = await this.diagnostic.requestLocationAuthorization();
    const reqLocEnable = await this.requestEnableLocation();

    //We get following success codes from cordova.plugins.locationAccuracy
    //{message: "All location settings are satisfied.", code: 0}
    //{message: "User agreed to make required location settings changes.", code: 1}
    const codes: any = [0, 1];

    if (reqLocAuthorization === 'GRANTED' && codes.includes(reqLocEnable['code'])) {
      this.initApp();
    }

  } catch (error) {
    // Looks like you have diss-allowed GPS, you need to resolve Geo Location in order to use this app :(
  }

}

Try/Catch is used to handle errors in async function. Comments make the code snippet self explanatory.

The whole detection process as done detectGeolocation() can be skipped. We can directly request for Authorization and Enabling of Location Services. It will silently handle the detection and only prompt user if needed.

Conclusion

I was caught up in this problem for weeks. I didn’t had the general understanding of how Location services work. There is dichotomy between using geolocation on the web and that on native mobile apps. Kindly jump in if you seek room of improvement in this solution.

2 Comments

  1. devx
    • Samiullah Khan

Leave a Reply

%d bloggers like this: