Such Android API levels, much confuse. Wow.

Such API Levels, Much Android, So confuse
I have been bitten more than once by the confusion of Android’s many API levels when building Xamarin.Android apps. It gets even more complex when you start referencing other libraries that target different API levels. Just the other day I had an issue come up with AndHUD where the resolution for a runtime error had nothing to do with the code itself. I decided it was time to finally write this post.

As if it weren’t confusing enough, Google generally gives three names to every API level: an integer API Level number, a version number, and a delicious sounding dessert name.

For example, Gingerbread was version 2.3 or API Level 9 (also Gingerbread had 2.3.7 and API level 10 as an update). Kit Kat is version 4.4, API level 19. Luckily Google has published the various versions in a table so you can figure out what is what.

When it comes to your Xamarin.Android apps, it’s important to be aware of all of the spots you can set API levels in your project settings. In particular, there are three places of interest:

  1. Project Settings -> General -> Target Framework
  2. Project Settings -> Android Application -> Minimum Android Version
  3. Project Settings -> Android Application -> Target Android Version

Android-API-Levels-Project-Settings

1. Target Framework

This setting is arguably the most important one. The Target Framework basically tells the compiler what API’s are available to compile your app with, at compile time. This setting really has no bearing on what API’s are actually available to your app to use on a device at runtime, but rather which API’s are potentially available.

In AndHUD, I wanted to be able to use Android.Animation.ValueAnimator (which is only available in API Level 11 and higher). If I had written code using that class and set my Target Framework to anything below API Level 11, I would have seen a compiler error saying the class ValueAnimator could not be found. Since I set the Target Framework to API Level 11, my code compiled with no issues.

Generally, you will want to set your Target Framework to be at least as high as the highest API Level required by any code in your app.

2. Minimum Android Version

This one’s pretty simple, it’s the lowest API level that your app will allow itself to be installed and run on.

Why would you want this to be different then the Target Framework? Well, in AndHUD, I wanted to make the progress circle animate when it changed. Since the ValueAnimator class was only available in API Level 11 or higher, I had to make a decision: Did I want to only support devices running API Level 11 or higher, or did I want to downgrade the user experience for older devices that didn’t support this animation?

I chose to support devices running older API levels. Since my Target Framework was set to API Level 11, I needed to set the Minimum Android Version to API Level 9 (2.3 Gingerbread), so the app would be allowed to still run on API Levels 9 and 10.

What this means, is that you can compile your app to use any API’s available up until the Target Framework, but your app will still run on devices running with API levels as low as your Minimum Android Version.

This doesn’t magically allow you to use unsupported API’s at runtime on devices that do not support them. This simply allows you to still run your app on a device that might not support some of the API’s your compiled app may be using. At this point it’s up to you to ensure at runtime that you don’t use any API calls which aren’t supported on the version of Android the device is currently running.

Downgrading Experience at runtime

If your Minimum Android Version is lower than your Target Framework, there are probably some devices that your app will run on which do not support all the API calls you’ve used in your app. In this situation you need to make decisions about how to downgrade your user experience when API’s are not supported on a device your app is running on. This may be cosmetic, or it could mean making some features or functionality available only to devices with newer versions of Android.

Since I decided to allow AndHUD to work on devices with API levels lower than 11, yet I used ValueAnimator which isn’t available on those lower API Levels, I needed to make sure that at runtime, I didn’t try to use the ValueAnimator class when it was not available.

To detect your API Level at runtime, you can access the Android.OS.Build.Version.SdkInt property. There are a number of constants to check this property against such as Android.OS.BuildVersionCodes.Honeycomb. Here’s how I dealt with downgrading the user experience in AndHUD:

// Get the version of Android we're currently running under
var version = Android.OS.Build.VERSION.SdkInt;

// Check to see if we're >= API Level 11 (HoneyComb)
if (version >= Android.OS.BuildVersionCodes.Honeycomb) {

  // It's safe to use ValueAnimator
  var va = (Android.Animation.ValueAnimator)Android.Animation.ValueAnimator.OfInt (progress, newProgress)
              .SetDuration (250);

  va.Update += (sender, e) => {
      var interimValue = (int)e.Animation.AnimatedValue;

      progress = interimValue;

      Invalidate ();
  };

  va.Start ();
} else {
  // Not safe to use ValueAnimator so let's just change the progress without an animation
  progress = newProgress;
  Invalidate ();
}

You can see the difference in the animation below. To the left, we’re running < API Level 11 without any animation to the progress circle as it advances. To the right, we’re running on >= API Level 11 with smooth animating of the progress circle.

AndHUD-Animation

How you downgrade user experience on older API Levels at runtime is going to be different depending on what API’s you’re actually using. There is no simple answer for this, you just need to use your best judgement.

3. Target Android Version

I left this one until the end for a reason. It’s probably not something you need to change unless you know exactly why you need to change it. My recommendation here is to leave this one set to Automatic – use target framework version which will automatically target the same version you picked for #1 Target Framework.

There are some edge cases you might need to set this property different, but I haven’t run across any myself yet.

UPDATE: There is one fairly popular edge case that has come to light since I originally wrote this post. You might want to use a higher Target Android Version than your Target Framework to satisfy aapt.exe’s compilation.

For example, with the AppCompat v7 bindings that Xamarin provides, Google has used some resource attributes that only exist in Lollipop (v5.0, API Level 21). You could set your Target Framework to v5.0 and everything will compile, but you might not want to have to worry about not using that many new API’s in your app. It is possible to set your Target Framework to v4.0.3 but set your Target Android Version to v5.0 to satisfy aapt.

But wait, there’s more (complexity)

Now that you understand the difference between Target and minimum Android version settings there’s one more curve ball to throw at you.

You may have noticed already that in Android Library projects, there’s only one place where you can change the Android version, and that’s #1 Target Framework. This makes sense, since a library cannot run on its own, and should have no opinion of which minimum Android version an app that uses the library should target (that would be rude).

In the case of AndHUD, the actual AndHUD library is set to Target Framework API Level 11. It’s generally good practice to make your Android library projects Target the minimum API level it needs to compile.

For library projects, this doesn’t mean you’re off the hook for checking Android versions at runtime, in fact, in a library that others are consuming, you should be extra careful about which API calls you use and whether or not they are supported at runtime. Try to be a considerate library developer: don’t crash other peoples’ apps!

It’s also very important to note that if you’re consuming an Android library in your Android application, your application’s Target framework must be set to as high, or higher than the Target Framework in the library project, or you will no doubt, run into errors just like in the AndHUD issue I referred to at the beginning of this post.

Hopefully that sheds a bit more light into how Android versions (API Levels) relate to your Xamarin.Android libraries and applications.

Good luck, and stay on the level!

iTunes Media HotKey Disabler

This simple application will allow you to disable or enable iTunes from listening to when you press the media keys (Play / Pause) on your keyboard. This is great for applications such as gTunes which make use of the hot keys but cannot themselves prevent iTunes from also responding to those keyboard keys.

itunes-media-hotkey-disabler

Why create this app?

While working on an upcoming Google Music app (gTunes) that’s currently waiting for approval on the app store, I wanted to make use of the media keys (Play/Pause, Next, Prev, etc.). This was easily enough done, however there was one major issue. Apple does not expose any API’s to prevent iTunes from opening when the Play/Pause keyboard button is pressed on a Mac. There are ways around this, but to my limited Mac development knowledge, none of them would be allowed on the App Store.

How does it work?

The most consistent and easiest way I’ve found to stop iTunes from listening for the Play/Pause button key was to stop the Launch Agent com.apple.rcd

If you’re more comfortable with Terminal, you can do the exact same thing that this app does with the command:

launchctl unload -w /System/Library/LaunchAgents/com.apple.rcd.plist

Similarly, the Launch agent can be re-enabled so that iTunes listens for the Play / Pause key again with the command:

launchctl load -w /System/Library/LaunchAgents/com.apple.rcd.plist

More interesting things

It’s worth noting I don’t know a lot yet about Mac development, but I’ve been able to create this app (and the upcoming gTunes) using Xamarin.Mac, creating a fully native app all in C#! You should check out Xamarin!

 

 

iOS7: Fun times with the new Full Screen Layout!

In a mad rush, I had to prepare an app for iOS7 after its release. Yes, I know, shame on me for not listening to everyone telling me to start getting my apps ready early. How bad could it be anyway?

For the most part, not too bad. The worst part for me came in the shape of dealing with this new idea that every UIViewController now expands the bounds of the entire screen, including where the status bar and navigation bars could be. In any case, I had to do a bit of learning really quickly. If you don’t already know what I’m talking about, here’s a picture of one unpleasant conversion experience:

http://i.imgur.com/wHK3KSO.jpg

At this point, many thoughts went through my head. I could just change the table view’s Frame right? Well then I would have to check if it’s iOS7 or not, and adjust according to iOS version, and and and… that just doesn’t seem right. Why would you do this to me, Apple?! At this point I took a deep breath, relaxed, and did what any competent developer would do: I Googled it.

This of course led me to StackOverflow, and several people asking the same thing. Why is my navigation bar and status bar appearing over my view?. There’s some pretty good answers there no doubt.

Everything new is old again!

Of course, the easiest way is just: make it work like it used to! This is entirely possible! All it requires really, is setting your view controller’s EdgesForExtendedLayout property to UIRectEdge.None. This was a quick fix, and ended up getting me up and running again until I could figure things out (you can of course choose some, all, or none of the edges to be used for extended layout with this property – for example, you might want the top to blur under the navigation bar, but the bottom to not blur underneath the tabs).

This was a workable solution, but I still wasn’t really happy with it. After all, the cool kids were all using the fancy blurred view scrolling behind the navigation and status bars like in the image below, and, who doesn’t want shiny and new?

blurred

Newfangledness $#&@*

So, what Apple really intends is to get a nice blurring effect of the contents of a scrollable view that happen to be under navigation bars, status bars, tab bars, etc. It’s really quite nice, if you haven’t seen it in action for yourself yet.

To make this happen, we essentially need to project our view to the bounds of the entire screen. The problem with this of course, is that we don’t want the top parts of our scrollable view to be initially hidden behind the navigation and status bars.

Content Insets to the rescue! (grab a coffee first)

If our view fills up the entire bounds of the screen, yet there’s still a status bar and navigation bar to show over top of it, we need a way to make sure the contents of our view aren’t initially hidden by the navigation and status bars.

For this purpose, we can take advantage of the ContentInset property that exists on any kind of scrollable view (eg: UITableView, UIWebView, UIScrollView, etc). This little gem of a property allows us to specify where our content should initially start, offset from the edges of the view that is holding it.

It’s important to note that Apple tries to help us out here. By default the UIViewController property AutomaticallyAdjustsScrollViewInsets is set to true, which means that in many cases, this will just work, and you won’t have to think about it. However, in practice you might run into some edge cases (haha, get it?) where the inset cannot automatically be inferred correctly, like I did.

In one case, my UITableView was not automatically adjusting the inset correctly. Long story short, I had to account for a status bar (20pt), and a navigation bar (44pt) for a total of (64pt) inset from the top edge of the screen. That meant I needed to set my UITableView.ContentInset = new UIEdgeInsets (64, 0, 0, 0);. The result was my UITableView still taking up the entire screen, but not making the top row initially hidden behind the navigation bar, while still taking advantage of the nice blurred scrolling underneath of it.

More dynamic?

You may have scoffed at my example of hard-coding the inset. All I can say is that sometimes you just need it to work immediately. If you’d like to do this more properly, you should consider the other new properties Apple has included on the UIViewController which are: TopLayoutGuide and BottomLayoutGuide. These serve as a reference to us to let us know what the top (and bottom) of our content should be within the bounds of the screen (by using the .Length property of Top/Bottom layout guides).

Now, there is one catch. As of this article being published, the .Length property was missing from the Xamarin API. There’s already a bug in for a fix, and in the meantime there’s a work around:

var length = MonoTouch.ObjCRuntime.Messaging.float_objc_msgSend (TopLayoutGuide.Handle, (new Selector("length")).Handle);

Oops, there’s another catch. This property doesn’t seem to return > 0 until the views have all been laid out. So, you may consider doing something like this:

public override void ViewDidLayoutSubviews ()
{
  base.ViewDidLayoutSubviews ();

   var length = MonoTouch.ObjCRuntime.Messaging.float_objc_msgSend (
                 TopLayoutGuide.Handle,
                 (new Selector("length")).Handle);

  TableView.ContentInset = new UIEdgeInsets (length, 0, 0, 0);
}

Also, don’t get caught with your pants down!

If you haven’t already guessed it, some of these properties are iOS7 only. So if you’re targeting iOS6 still, you’ll have to do some sort of version checking to make sure you only use these API’s when the app is running under iOS7!

Anyway, I hope this finds its way to someone else who is going through the same learning pain as I did, to get their app ready for iOS7!

iOS7 Recipe: Background Fetching

This is my entry into the Xamarin Recipe Cook-Off. Recipes, in Xamarin terms, are very simple demonstrations of how a single feature or piece of functionality is implemented. I thought background fetching would be useful to many developers, and it’s pretty easy to implement, especially after reading this recipe.

I’ve also included the recipe in this blog post:

Background Fetching Data

This recipe shows how to register your application to perform background fetching on intervals.

1. Recipe

In your application’s Info.plist file, add the value fetch to the UIBackgroundModes (Required background modes) property.

Next, in your AppDelegate class, in the FinishedLaunching override method, add the following code to register your application for background fetching:
UIApplication.SharedApplication.SetMinimumBackgroundFetchInterval (UIApplication.BackgroundFetchIntervalMinimum);
Finally, in your AppDelegate class, override the PerformFetch method.

This method will be executed by the operating system when it sees best fit (eg: when the device is awake and connected already). You do not have complete control over how often or when fetching happens.

You should execute your own code to fetch new data in this method. It’s important to call the Action<UIBackgroundFetchResult> completionHandler parameter which is passed into this method with the appropriate result when you are done.

2. Sample PerformFetch

In this sample, a weather service is called by background fetching so that when the user opens the app, recent weather is available. The weather is cached locally after it’s fetched in the background, and the UI is also updated if there is new weather info.

public override async void PerformFetch (UIApplication application, Action<UIBackgroundFetchResult> completionHandler)
{
  Console.WriteLine ("PerformFetch called...");

  //Return no new data by default
  var result = UIBackgroundFetchResult.NoData;

  try
  {
    //Get latest weather
    var w = await GetWeatherAsync("Windsor, Canada");

    if (w != null)
    {
      //Cache the weather locally
      CacheWeatherAsync(w);

      //Update the UI
      weatherViewController.UpdateWeather(w);

      //Indicate we have new data
      result = UIBackgroundFetchResult.NewData;
    }
  }
  catch
  {
    //Indicate a failed fetch if there was an exception
    result = UIBackgroundFetchResult.Failed;
  }
  finally
  {
    //We really should call the completion handler with our result
    completionHandler (result);
  }
}

3. Additional Information

  • Your PerformFetch has about 30 seconds to run before it’s killed
  • The operating system is more likely to grant more time (and more often) to your application for background fetching if you are efficient, which means executing quickly, and always calling completionHandler with an accurate result
  • You can tell the operating system the minimum time to sleep between waking up your application and calling its PerformFetch method if you know your app only updates at a certain interval, to avoid extra calls to PerformFetch and wasting battery life. You would specify the minimum time in seconds in the UIApplication.SharedApplication.SetMinimumBackgroundFetchInterval (double minimumBackgroundFetchInterval) method
  • You can actually make calls to update your UI from the PerformFetch method so that the next time the user launches the app, everything is up to date

How to Auto Wire Up Android Activity Views in Xamarin.Android

One thing that’s occasionally bothered me was how verbose it is in Android to wire up views from a layout, in an activity. I finally was fed up enough to write a simple little helper that does this based on reflection. Consider the following verbosity monstrosity:

[Activity (Label = "RandomDataActivity")]            
public class RandomDataActivity : Activity
{
  Button button1; Button button2; Button button3; Button button4;

  TextView textView1; TextView textView2; TextView textView3;
  TextView textView4; TextView textView5; TextView textView6;
  TextView textView7; TextView textView8; TextView textView9;

  ImageView imageView1; ImageView imageView2; ImageView imageView3;
  ImageView imageView4; ImageView imageView5; ImageView imageView6;

  protected override void OnCreate (Bundle bundle)
  {
      base.OnCreate (bundle);

      SetContentView (Resource.Layout.RandomDataLayout);

      button1 = FindViewById<Button>(Resource.Id.button1);
      button2 = FindViewById<Button>(Resource.Id.button2);
      button3 = FindViewById<Button>(Resource.Id.button3);
      button4 = FindViewById<Button>(Resource.Id.button4);

      textView1 = FindViewById<TextView>(Resource.Id.textView1);
      textView2 = FindViewById<TextView>(Resource.Id.textView2);
      textView3 = FindViewById<TextView>(Resource.Id.textView3);
      textView4 = FindViewById<TextView>(Resource.Id.textView4);
      textView5 = FindViewById<TextView>(Resource.Id.textView5);
      textView6 = FindViewById<TextView>(Resource.Id.textView6);
      textView7 = FindViewById<TextView>(Resource.Id.textView7);
      textView8 = FindViewById<TextView>(Resource.Id.textView8);
      textView9 = FindViewById<TextView>(Resource.Id.textView9);

      imageView1 = FindViewById<ImageView>(Resource.Id.imageView1);
      imageView2 = FindViewById<ImageView>(Resource.Id.imageView2);
      imageView3 = FindViewById<ImageView>(Resource.Id.imageView3);
      imageView4 = FindViewById<ImageView>(Resource.Id.imageView4);
      imageView5 = FindViewById<ImageView>(Resource.Id.imageView5);
      imageView6 = FindViewById<ImageView>(Resource.Id.imageView6);
  }
}

Now that’s a lot of code to do something really simple. Plumbing code that’s so simple I’d rather not, and shouldn’t have to waste my time on it! How about this instead:

[Activity (Label = "RandomDataActivity")]            
public class RandomDataActivity : Activity
{
  Button button1; Button button2; Button button3; Button button4;

  TextView textView1; TextView textView2; TextView textView3;
  TextView textView4; TextView textView5; TextView textView6;
  TextView textView7; TextView textView8; TextView textView9;

  ImageView imageView1; ImageView imageView2; ImageView imageView3;
  ImageView imageView4; ImageView imageView5; ImageView imageView6;

  protected override void OnCreate (Bundle bundle)
  {
      base.OnCreate (bundle);

      SetContentView (Resource.Layout.RandomDataLayout);

      this.WireUpViews ();
  }
}

Here’s the extension method I created to do this:

public static class ActivityExtensions
{
  public static void WireUpViews(this Activity activity)
  {
      //Get all the View fields from the activity
      var members = from m in activity.GetType ().GetFields (BindingFlags.NonPublic | BindingFlags.Instance)
                    where m.FieldType.IsSubclassOf (typeof(View))
                    select m;

      if (!members.Any ())
          return;

      members.ToList ().ForEach (m => {
          try
          {
              //Find the android identifier with the same name
              var id = activity.Resources.GetIdentifier(m.Name, "id", activity.PackageName);
              //Set the activity field's value to the view with that identifier
              m.SetValue (activity, activity.FindViewById (id));
          }
          catch (Exception ex)
          {
              throw new MissingFieldException ("Failed to wire up the field "
                                               + m.Name + " to a View in your layout with a corresponding identifier", ex);
          }
      });
  }
}

Ok, ok, I know it’s not perfect, but it’s a bit of a time saver, and keeps my code looking a bit neater. In a perfect world I should just be able to use an android identifier as if it were already a declared as a code field. There’s also room for improvement in my extension method, for example, what if you declare a field that’s a View but not in the layout, but you did this intentionally? Well, I don’t want to do ALL your work for you 😉

Just wanted to share this little bit with you. Hopefully it sparks some ideas for something greater in your day! Happy Coding!

Xamarin Studio Launcher

UPDATE: Sep 19, 2014: Yet another new Launcher! This time I’m calling it v3, and it can now handle .sln files (opening them in a new instance of Xamarin Studio). Check out the new blog post for more info!

UPDATE: Sep 8, 2014: The original launcher works well, but after Xamarin 3.0, it didn’t look so up to date. There were a couple people that took it upon themselves to update it, and thanks for that! Now, I’ve released my own updated copy, so please download and try again!

Xamarin Studio Launcher

I’ve recently converted to a Mac. As a long time Windows user, one thing I was very accustomed to was keeping multiple visual studio, or more recently, Xamarin Studio instances open at any given time. Switching to a Mac I found this isn’t so easy, so I decided to make a nice little Launcher application to open new Xamarin Studio instances at will!

So, without further ado, please download the Xamarin Studio Launcher!

Download Xamarin Studio Launcher

MobiDevDay Detroit 2013

Had a great turnout and lots of solid questions at my talk on Xamarin and C# at Detroit MobiDevDay 2013. I’ve got my slides posted for anyone who cares to have a look!

Thanks to @MobiDevDay for having me, and to all those who came out!

MobiDevDay Detorit – Native Cross Platform Mobile with Xamarin and C

Create iOS, Android, Mac, and Windows Phone apps in C#. Reuse code, and leverage existing .NET libraries and frameworks, while applying the same C# skillset everywhere to create truly native apps across mobile platforms. This session looks at why you’ll love using Xamarin’s popular mobile development tools to create native applications to increase productivity, while creating a first class native user experience across the most popular mobile platforms. This isn’t your grandmother’s hybrid web app, this is real native, platform API’s, and raw power.

Xamarin Evolve 2013

Xamarin Evolve 2013 was an Awesome conference! I got to see a lot of familiar faces, and meet plenty of new ones! It’s such a great experience to see and talk with such great people who I’d only otherwise know online!

I also had the great privilege to do some speaking at Evolve! I’ve posted my slides below and will update the post with links to the videos when they are available!

Thanks to Xamarin and everyone who made this such a great event!

Push Notifications with PushSharp

Push Notifications are a great way to update users of you app with alerts and information in an effective, standard, and efficient way. Come and learn about what Push Notifications are and how they work on all the mobile platforms, and how you can use PushSharp to deliver notifications to your apps!

Speaker Deck – Push Notifications with PushSharp

Barcode Scanning with ZXing

Barcodes have become increasingly popular in the Mobile space. Learn how you can easily include scanning support with custom overlays using the ZXing.Net.Mobile component. You will also learn how to generate barcodes from within your apps. This session will also discuss various barcode scanning options, and the making of the ZXing.Net.Mobile component.

Speaker Deck – Cross Platform Barcode Scanning with ZXing

A Month With Android

Just before the new year, I wrote a post about switching back to Android (to a Nexus 4), and I was excited at the prospect. I explained that I’d been a long time iOS user (quite happily so), except for a brief stint on Android 2.3 (Gingerbread) which ended not so well.

Well, it’s been about a month now since I’ve switched back to Android, and I’m not looking back anytime soon! I’m going to do a quick recap about the things I love, and the things I miss:

What I Love

  • Pre-Load All the Things! This is something I’m surprised people don’t complain more about, and one thing that has bothered me about iOS since day one. It’s gotten better with faster devices and faster network connections, but I REALLY hate getting for instance, a Twitter notification, and then once I launch the app, having to wait for the item that triggered the notification to be loaded. I really love it when Android apps go out and prefetch this data when a Push Notification comes in, so that when I decided to act on the notification and open the app, the data is already there. The same goes for email. If you don’t want to use the default mail app, every time you open the mail app (Gmail for instance), you must wait for the data to load, even though you probably already know who the email is from since it told you in the push notification. I cannot stress enough HOW MUCH TIME this has given back to me on Android.
  • Real Estate Maven I always thought the bigger phones were too big. I drank the iPhone screen size Kool-Aid, but I loved the bigger iPhone 5. I will say that 6” seems too big still, but my 4.7” Nexus 4 screen is just awesome. It still fits easily in my pocket, and the added real estate is great for typing, and browsing. Even the iPhone 5 feels too tiny now when I have it in my hands.
  • The Google Experience I’m a big user of Google services, so it comes as no surprise that I love the Google apps on Android. Google has recently improved its iOS offering dramatically, but at the end of the day it still works just a bit better on Android.
  • Settings Quick Toggles In the pull down notification bar, there’s a button that flips to a view of tiles of several shortcuts to settings, such as Brightness, WiFi, Airplane mode, Bluetooth. In 4.2.2, you can now quickly toggle some of these things on and off from this menu. So, to toggle WiFi, I swipe down, tap the settings button, and tap and hold the WiFi. Pretty quick and less annoying than iOS

Quick-Toggles

  • Apps without Borders One thing that always bugged me about iOS as an end user was how each app felt like the lonely island it was. I love in Android how when I tap a link, or perform some action, I’ll get a little menu asking me which App I’d like to have handle this action. iOS does this to an extent now, but Android is better at it, and Android effectively lets me choose a default App to deal with the content type. I love not being forced into using the default Mail app or Browser, if I don’t want to!

Share-Content

  • Google Now Siri is great, but Google Now is better in almost all respects. I find the voice transcription way faster and more accurate, and Google Now’s ‘card’ design really works for me. If you can get over the fact Google is in your email, you can learn to love having a card pop up with tracking info on the package you just ordered, or movie tickets you bought. There’s so much depth to Google Now it could be its own post, but it’s safe to say I really like it.

Google-Now-Cards

  • Notifications I’ve always liked Google’s notification bar way better than how iOS deals with it, so I’m not surprised to feel right at home with it. I am pleasantly surprised, however, at how useful having an LED indicator for notifications is. The LED basically allows me to decide if I need to even turn my screen on or not. I also really like how apps are starting to take advantage of rich notifications in the pull down tray. Music apps allow me to skip next, twitter notifications allow me to tap reply right from in the tray. This is a really strong point for Android, and I find myself wasting much less time on Notifications than I did in iOS

Rich-Notification

  • UI This is where many of you will disagree with me. I actually have taken a strong liking to the Android UI, or at least the apps that do a good job of it. If you haven’t played with Android recently, you may not realize that developers have started to take care with how they design their apps. There’s still a lot of junk out there, but for nearly any App I use on a regular basis, there’s a very nicely designed app Available now.
  • Lock Screen There’s three things I love about the lock screen on Android. Using a pattern to unlock my screen as opposed to a numeric code, Having widgets on my lock screen, and specifically, DashClock which adds many notification icon types to the lock screen (much like windows phone 8) – It’s a beautifully designed app and something I’d love to see integrated right into Android

Lock-Screen

  • FREEEDOM!!! Seriously though, it’s really liberating not being told you can’t do something on your device. If I want to use a different keyboard, I can. If I want to use a different default Mail app, I can. I am sick of Apple telling me to do things a certain way. I realize for most users, that is fine, but I’m a power user darnit, let me tweak!

What I Miss

There’s a few things I do, genuinely miss from iOS. Luckily, none of them are really dealbreakers for me:

  • iMessage Many of my friends and family (including my wife) have iPhones. I have unlimited texting, so it’s not that big of a deal not to have iMessage, but I found it oddly more reliable than sending text messages (especially between carriers) in some cases. I’ve mostly switched to Facebook Messenger if I’m chatting with a friend who’s on facebook (which most are).
  • Fit & Finish I really only added this in because I felt a bit of a traitor since my list of things I miss is so short. There is some truth here though, there’s plenty of apps that look nasty. Luckily, most of those apps are apps I do not use. At this point the market is mature enough that you can pretty much find an app that looks good to do whatever you need. I expect this to only get better!

These are a few of my favourite apps

After all this talk, I thought it would be a good idea to show what Apps I use regularly. Here’s my top 10:

  1. DashClock – I already mentioned it, and it’s not really an App, but a lock screen widget. If you have Android 4.2+, you MUST get this app, and some of the addons for it
  2. Carbon for Twitter – It’s relatively new, but this is the Twitter app Android has been waiting for
  3. Facebook – OK, my friends are all doing it, so I need it to. The App is quite well done (native) on Android nowadays
  4. Feedly – I use Google Reader, and it was a struggle to find a decent app for it. Feedly fills this gap for me
  5. Podkicker – Podcasts occupy my long commutes, so a decent podcast app is a requirement. Doggcatcher is good too, but a bit overly complicated. Podkicker is lean, fast, simple, and looks nice
  6. Chrome, Gmail, Google Talk – I’ll lump these all together since they come by default, but they really are very well done. I love using Chrome on my mobile!
  7. Dropbox – I tend to use this one daily. It’s very solid and well constructed for android.
  8. Google Maps – It’s still better on Android than iOS! I love the offline caching feature too, so useful as I live near Detroit and go over there a lot, but don’t want to incur the roaming data fees
  9. BaconReader – This is my reddit client of choice
  10. 1Weather – a beautiful weather app. Here’s a great example of the potential for nice looking apps on Android

So, to sum it all up, I’m very happy with my Nexus 4. Both from a hardware perspective, but I’m also really enjoying Android 4.2, it feels much more polished, useful, functional, efficient, etc.

Why I’m Looking forward to Android

iOS-to-Android

The Back Story

Way back in Froyo days, I took the leap from my iPhone 3G to Android as my daily device with a Samsung Galaxy S. I was co-authoring a book Professional Android Development with Mono and C#/.NET

Android was new, it was exciting, it was different. It was also slower, higher maintenance, and had me flashing roms weekly. Not necessarily a problem for a supergeek like me, but still tiresome and prone to moments of Oh sorry, that’s a bug in my phone’s rom or my battery’s dead because of all the services i have running.

Needless to say, it wasn’t very long before I was back on the iPhone train. I was content with the iPhone 4, and then the iPhone 4S, and now the iPhone 5. They’re all great devices, they just work… as long as you want to use them how Apple intends.

The primary reasn I’m switching back to Android, is my Galaxy S just doesn’t cut it for development anymore. My wonderful wife will inherit my iPhone 5 (like she does all my devices), and I’ll have a Nexus 4 to test on soon.

Why I’m looking forward to Android

I have a Nexus 7. It’s quite nice. I like it better than the iPad, with the exception of a lack of apps in some areas (games). Android 4.2, I feel, finally starts to get things right. Sure there’s still issues, but by and large it’s a good operating system. The eco-system is also quite mature now. Most, if not all the apps I use daily on iOS (which seems to be less nowadays) all exist in a reasonably good form on Android (save for maybe a really good Twitter client, but that’s something I’m currently working to fix!).

I’m getting excited for Android. See, the iPhone was great, but there are a lot of compromises I’ve had to make to be a happy iOS user. When I think about the things that bug me with iOS, Android largely has them right:

  1. Gmail: Ok, Google JUST released a better Gmail app for iOS again. They actually did this just after I ordered my Nexus 4. It’s much better, however it’s still not as awesome as Gmail on Android.
  2. Default Apps: Chrome, Gmail, Google Maps, all great apps and services. But on iOS, I can’t choose to have links open in Chrome, I can’t choose Gmail as my default mail client, nor can I have Google Maps default for navigation. I love that on Android I can finally do these things.
  3. LockScreen Patterns: I have a confession: I’ve not got any passcode set on my iPhone. I hate typing in passwords every time I want to unlock my screen. One thing I loved on Android was the pattern unlock. It felt much quicker, more intuitive, just easier. I’m happy to get back some security with little pain!
  4. Lockscreen Widgets: This is a pet peave of mine on iOS. At least notifications show up now, but I want to be able to see a bit more information so I can glance at the lockscreen and decide if I should open my phone or not. This is welcomed in android!
  5. Notification Bar: Google invented the notification bar. It’s way better than iOS’s. I love how it shows a small icon in the status bar at the top of the screen, alluding to there being more notifications. I also like how rich notifications can be in Android, and that I can swipe individual ones away, or clear the whole lot of them. It’s just a much better implementation.
  6. Google Now: Siri is great, but Google Now seems more well thought out. Since I already use gmail, I’m looking forward to getting cards with shipping status of things I’ve ordered, or boarding passes, automatically, without me telling it. This is a great system that surely requires some tweaking yet, but the idea that Google can give me the information I want when I need it, without me asking for it is awesome!
  7. Google Maps: Just like Gmail, google JUST released a maps app for the iPhone. It’s actually really, really good! I am however, still looking forward to being able to cache some areas offline, and having Google Maps used as the default navigation app on my OS.
  8. No Lightning: I still have only one lightning cable, partially because they’re hard to find, and partially because I HATE spending $20 on a usb cable. I do love that the cable is reversable, but it’s not compelling enough for me not to be excited about having an endless supply of charging cables again 🙂

What I’ll Miss

iphone-sad

Let’s be honest. There’s some things iOS just does right. I’ll no doubt miss several things about my iPhone, but I think we’re finally at the stage the things I miss on Android are greater than those I miss on iPhone:

  1. Apps! Yeah, the Android ecosystem is WAY better than back in Froyo days, but iPhone still wins when it comes to games, and just sheer quantity of quality apps. I’ll miss this, though not as much as I would have years ago.
  2. Fit & Finish: iPhone is a very polished OS. There’s no denying this. Android has made strides to improve the butteryness of the interface, but iPhone is still king for that polished feeling.
  3. Siri: One thing I already know google now can’t do is create reminders for a future day. I’m sure this will get added at some point, but it’s one thing I use a lot with Siri right now, and I’m going to miss it!
  4. Airplay: This is actually the big thing I’m going to miss. I have two Apple TV’s, and while I don’t use it a lot, Airplay screen mirroring is incredibly useful when I do want it. Android just doesn’t do this, and there’s no silver bullet in sight. I guess I’ll have to pull out the iPad when I want to do this! At least I can still control my iTunes remotely on Android and have it play to my AppleTV!

What’s Next?

It’s hard to say whether I’ll love Android, or find some of the same things annoying that caused me to switch back to iPhone. I’m sure there will be some remorse at times, but I think overall, I’ll really enjoy being back on Android for all the right reasons. Plus, now I can finally stop having people ask me why I use an iPhone once they find out I helped write a book on Android programming! Stay tuned, I’ll be posting again after using my Nexus 4 for awhile to see how it’s going!