Programming Stuff

Android Photo & Video Programming Course Almost Ready

For the past month I’ve been working on my next Pluralsight course: Android Photo & Video Programming. … I just finished recording the video for the last module.

Still have some more work to do editing the videos, preparing the course assessments, etc. but the hard work is done.

I have to say, this has been one of the most fun courses to write I’ve done. There’s something cool about taking control of the camera, rendering the live preview directly within one’s app View hierarchy and snapping a picture or recording a video.

Something I had thought was going to be a minor point that I ultimately found really interesting was controlling zoom.

The basic zoom-in/zoom-out stuff was just the beginning. Controlling the out-of-band smooth zoom and managing the callbacks that occur during the zoom process were really fun.

The course also ended having much more information than I had originally expected. I had originally spec’d the course out for 5 modules but ended up with 7 jam-packed modules – here they are…

  • Getting Started
  • Directly Accessing the Camera
  • Viewing the Camera Preview Display
  • Taking a Picture
  • Camera Control
  • Recording Video
  • Media Store

If all goes as expected, I’ll have everything turned in to Pluralsight early next week and the course will be live a short time later. I’ll be sure to let everyone know when it goes live.

Here’s a list of Jim’s other Pluralsight Courses…

PSAndroid_216x155

Programming Stuff

Avoiding Android App Crashes Caused by Device Orientation Changes

A challenge commonly faced when first developing in Android is the potentially frequent destruction and reconstruction of an Activity. The most common time this occurs is when the user rotates the device between horizontal and portrait orientations.

Many an app that runs fine during testing suddenly crashes when put into a user’s hands simply because the user tilted the device one way or another.

This crashing usually occurs because device orientation changes cause the Android framework to tear down the displayed Activity along within any contained Views, and then to fully reconstruct the Activity/View hierarchy. Any references to the Activity or to the Views within the Activity suddenly become invalid. Similarly any references within the Activity or Views that were set as a result of a user action or similar are now lost.

There are a number of ways to deal with this issue but one of the easiest is to take advantage of Fragments.

NOTE: You can use the configChanges attribute on your Activity’s manifest entry to prevent the teardown/reconstruction process caused by orientation changes but that has its own headaches.

Fragments won’t automatically resolve this issue because, by default, when the Activity is torn-down in response to an orientation change the Fragment contained within the Activity is also torn down along with any contained Views.

The solution lies in an underused method: Fragment.setRetainInstance.

Calling setRetainInstance with a value of true causes Android to preserve the Fragment across the teardown/reconstruction cycle of an Activity. Along with the Fragment, the Views or other object references contained within the Fragment or Views remain.

With setRetainInstance(true) called on a Fragment instance … when an orientation change occurs, Android…

  1. Holds a reference to the Fragment instance
  2. Tears down the old Activity instance
  3. Creates a new Activity instance
  4. Attaches the preserved Fragment instance to the new Activity instance

With that, the Fragment, contained Views and object references, remain intact.

Something to keep in mind though … because your Fragment instance will be moved between different Activity instances, you should avoid caching a reference to the Activity. Instead call Fragment.getActivity anytime you need to reference the Activity.

Jim talks more about Fragments in his Pluralsight course…

AndroidFragments_400x100

Programming Stuff

Android 4.x jumps from 45% of Android devices to nearly 55% overnight

That’s right if you look at the Android Dashboard Charts for the current period (period ending April 2, 2013 as of this writing) you’ll find that the combination of 4.0, 4.1, & 4.2 devices is 54.3%.

AndroidChart_2013-04-02

If you looked at the chart for the previous period you find that same family of devices had only 45% of all Android devices. How does one account for such a huge jump?

Well – one way is to change the way one counts. 🙂

You’ll find the following note on the Android Dashboard Page:

Note: Beginning in April, 2013, these charts are now built using data collected from each device when the user visits the Google Play Store. Previously, the data was collected when the device simply checked-in to Google servers. We believe the new data more accurately reflects those users who are most engaged in the Android and Google Play ecosystem.

So basically .. they now count devices that actually attach to Google Play rather than counting every single device that just happens to wake up periodically and send a heartbeat to the Google servers.

So the cynic might say that Google is skewing things for their own advantage (I’m not saying they’re unhappy with this new way of counting) but I don’t really think that’s the case here.

Honestly, most of us looking at those charts are interested in seeing what versions of the platform we should target with our apps. Those apps are distributed via Google Play … so, I agree that this is the “right way” to count.

For information on creating apps for Android 4.x, checkout Jim’s Pluralsight Course

Android40WhatsNew_350x100

 

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

Fun Life Stuff

New WDW Fantasyland Stuff

Bonnie and I had a chance to visit Magic Kingdom over the weekend.

We normally stay away from parks on big holiday’s like Easter but we decided to take a chance on Saturday. We had low expectations and decided in advance that we’d just “roll with it”.

I have to say we had great fortune. The park was, of course, packed but we were able to move around easily for the most part and thanks to FastPass were able to have some great fun.

If you follow the Walt Disney World thing, you know that there’s lots of new stuff that’s opened recently and continues to open in Fantasyland. Here’s a few things that were new to me this weekend (they may have been visible for a little while now … but I hadn’t seen them before).

The 7 Dwarfs Mine Train continues to grow

7DwarvesRollerCoaster

A new Rapunzel tower right next to the Haunted Mansion

Rapunzel01

Repunzel02

Some fun posters from Rapunzel characters (these guys appeared in the tavern)

HookHand

Vladamir

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.