Category: Programming Stuff

Programming Stuff

Android Network Locates: When Enabled is NOT Enabled

The Network Location Provider is a key part of an Android location-based solution because it is far more power efficient than GPS and works in places where GPS doesn’t (of course GPS works in places the Network Location Provider doesn’t so it’s often good to use both).

The Network Location Provider capitalizes on the Wi-Fi and cellular radios within your phone to estimate location. This, of course, means that the Network Location Provide only works when those radios are working … and this is where we can easily run into trouble.

Prior to using a location provider, it’s always a good idea to confirm that the user hasn’t disabled it. According the Android docs, the code in the following function checks that the Network Location Provider is enabled.

  // Check that Network Location Provider reports enabled
  boolen isNetLocEnabled(Context context) {
    LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    return lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
  }

What that code actually checks is whether the user has the Location Service enabled … basically … is the following box checked in the device settings?

LocationSettings_251x397

But what that code does not check is whether the phone’s Wi-Fi radio is turned on or if the phone is in Airplane mode …. that’s these device settings …

WiFiSettings

AirplaneSettings

If the user disables Wi-Fi, the Network Location Provider can no longer use the Wi-Fi system and will be limited to cellular towers for locates. Using cellular towers generally provides very limited accuracy (in the area of 1 to 3 kilometers … not accurate enough for most systems).

If the user puts the phone in Airplane mode, neither Wi-Fi nor the cellular radio are available .. in this case, the Network Location Provider will simply never report any location values.

And here’s the problem – in both of these cases, LocationManager.isProviderEnabled will still report that the Network Location Provider is enabled. This is a false positive.

To safely use the Network Location Provider, we need to explicitly check the Wi-Fi and Airplane Mode, settings. The following code shows how we can check those.

  // Check Wi-Fi is on
  boolean confirmWiFiAvailable(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo wifiInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    return wifiInfo.isAvailable();
  }

  // Check Airplane Mode - we want airplane mode off
  boolean confirmAirplaneModeOff(Context context) {
    int airplaneSetting =
      Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) ;
    return airplaneSetting == 0;
  }

Using the above 2 functions along with the isNetLocEnabled function from earlier in this post, we can now use the following function to determine if the Network Location Provider is really usable.

  bool isNetLocUsable(Context context) {
    return
      isNetLocEnabled(context) &&
      confirmAirplaneModeOff(context) &&
      confirmWiFiAvailable(context);
  }

With that, we can now be sure that the Network Location Provider is enabled and the underlying services it relies upon are also available.

For complete certainty, in addition to checking the Wi-Fi and Airplane Mode settings prior to using the Network Location Provider, we should also continuously monitor the Wi-Fi and Airplane Mode settings (notification mechanisms exist for each) the entire time we’re using the Network Location Provider. Doing so allows our application to respond accordingly should the user change either setting while we’re using the Network Location Provider.

This post is adapted from Jim’s Plurasight Course

AndroidLBS_436x155

For more information about Jim and his courses visit his Pluralsight Author Page

Programming Stuff

Android 4.2.2 ADB Device Offline Mystery Solved

As I mentioned in yesterday’s post, I lost the ability to debug code running on my device after upgrading the device to Android 4.2.2. And as mentioned in that post, the solution was to upgrade to the latest Android Platform Tools.

Well … after checking out the Android Debug Bridge (a.k.a. ADB) docs, it turns out that what I experienced is a documented behavior.

Starting with Android 4.2.2 the platform will not allow debugging unless the user is prompted with a dialog box showing an RSA key passed from the connected desktop. This is a new security feature that assures debugging cannot be initiated on the device without a specific acknowledgement from the user.

In order for ADB to successfully make the required exchange to the device you must have a version of ADB that ships with Android Platform Tools r16.0.1 or higher installed (as of this writing the current Android Platform Tools version is r16.0.2).

So it’s a good thing but a bit frustrating when first encountered.

Programming Stuff

Android ADB reports device is “offline”

Device upgrades are so often a good-news-bad-news situation … and so was the case of my device’s upgrade to Android 4.2.2 over the weekend.

I love this latest version of Android – in addition to just generally being a good update, it also has a sweet new camera and, some cool new clock/stopwatch/timer features.

The new camera features are especially cool for me as I’m right in the midst of writing a new Android developer course Android Photo and Video Programming for Pluralsight.

But like so many exciting weekend events, Monday often comes with regret … and so it was today.

I fire up my favorite Android IDE (currently JetBrains IntelliJ IDEA), connect my device, then launch the debugger … and it’s then that I see “waiting for device” … I keep waiting, waiting, waiting.

To check things out, I do an ‘adb kill-server’ followed by an ‘adb devices’ and I see…

List of devices attached
99999C99999D999         offline

That’s something I don’t see too often so I do the standard stuff … reboot my desktop computer, reboot the device. Always the same result … the device reports being offline

The Answer….

I resolved the issue by upgrading to the latest version of the Android SDK Platform-tools – for me, that’s version 16.0.2:

AndroidSDKManager-PlatformTools16.0.2

Just something to remember … you may have to run the SDK Manager more than once to get all of the latest updates.

In my case, I had to…

  • Run the SDK Manager
  • Execute ‘Install packages…’
  • Exit the SDK Manager
  • Restart the SDK Manager
  • Execute ‘Install packages…’

Only then did I get the necessary updates to resolve the offline issue so that I now see the much more familiar (and welcome) device message in ADB.

List of devices attached
99999C99999D999         device
Programming Stuff

Programmatically Enable Android GPS and Location Services

I remember the “good ol’ days” of location-based programming where there was a simple API call that allowed an application to enable or disable a mobile device’s GPS service. Today, user privacy and security concerns make that sort’a thing no longer possible.

In today’s world, a phone’s user generally has ultimate control of what features are and are not enabled on their phone. Although I agree this behavior is best for users, it definitely creates headaches for developers.

The one thing we know we can’t do as developers, is display a message that simply says “Hey! Go turn on your GPS”. Seeing a message like that would cause most users to uninstall our app and look for an app that’s easier to use.

The good news is that as developers we can send the user directly to the location settings screen right from within our app with a simple Intent.

Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);

The exact format of the screen the user sees will vary based on their Android version and device model, but the above code will always take them to the appropriate settings screen. On my Samsung device, the ACTION_LOCATION_SOURCE_SETTINGS screen looks like the following…

LocationSettings

In general what I’ll do is use the LocationManager class to check for the availability of the required location services. If the services aren’t enabled,  I’ll show an AlertDialog informing the user of what they need to do and then show the settings screen in the dialog’s click handler. Here’s that code…

// Get Location Manager and check for GPS & Network location services
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
if(!lm.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
      !lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
  // Build the alert dialog
  AlertDialog.Builder builder = new AlertDialog.Builder(this);
  builder.setTitle("Location Services Not Active");
  builder.setMessage("Please enable Location Services and GPS");
  builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
  public void onClick(DialogInterface dialogInterface, int i) {
    // Show location settings when the user acknowledges the alert dialog
    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
    startActivity(intent);
    }
  });
  Dialog alertDialog = builder.create();
  alertDialog.setCanceledOnTouchOutside(false);
  alertDialog.show();
}

That little bit of code can go a long way to both ensuring that your app has access to the required location services and that the user has a positive experience.

This post is adapted from Jim’s Plurasight Course

AndroidLBS_436x155

For more information about Jim and his courses visit his Pluralsight Author Page

Fun Life StuffProgramming Stuff

Just getting started

I was an avid blogger for many years when I was consulting and working as a trainer. As my work moved me away from those things, I stopped blogging and haven’t done so for several years.

Well … I’m back to consulting and working as a trainer and am feeling the itch to start blogging again …so that’s what I’ll be doing. 🙂

Most of what I blog will be technical software developer stuff (focused primarily on Android with some iOS on the mobile side / .NET on the server side). I’ll also being doing some fun stuff from life (being in Celebration, FL – 3 miles from Disney World – offers lots of opportunity for that). There’ll also be some spiritual stuff now-and-then as well.

Other online places you can find me…

I hope you find things enjoyable