Redth

code, ramblings, rants

New and Improved Xamarin Studio Launcher

| Comments

Awhile back I made a quick little AppleScript based app called Xamarin Studio Launcher to help launch multiple instances of Xamarin Studio (it had a pretty little icon that you could keep in your dock to open new instances - which I recently updated to the newer Xamarin look).

Xamarin Studio Launcher

While it was cute, and relatively functional, as a recovering ex-Windows user, I found myself still constantly opening .sln files from finder, which would cause them to open in an existing instance of Xamarin Studio, closing whatever current solution happened to be open in that instance.

Now I know about the ability to open multiple solutions in the same Xamarin Studio instance, and generally I’m pretty good about forcing myself into learning the nuances of the platform I’m working on, however, having multiple instances of Visual Studio open was something I grew so accustomed to that I just couldn’t shake the habit of being on a Mac!

Not sure why it took me so long to make this, but here it is, finally!

Xamarin Studio Launcher v3

This new launcher app works first and foremost exactly like the previous Xamarin Studio Launcher I released. You can put it in your dock, and when you open it, it will launch a new, blank instance of Xamarin Studio.

The new feature is that it can now handle opening .sln files. If you choose to open a .sln file with this app, it will open that .sln file in a new instance of Xamarin Studio.

This means you can set Finder to open all .sln files with Xamarin Studio Launcher so any time you double click or otherwise open a .sln file from Finder, it will open in its own instance of Xamarin Studio!

How to set this as the default app for .sln files

Xamarin Studio Launcher

  1. Find a .sln file in Finder
  2. Right click the .sln file and Get Info (or highlight the file and cmd + i
  3. Under the Open With section, click the drop-down list and click Choose
  4. Navigate to and select Xamarin Studio Launcher
  5. Click Change All

Download

Here’s the .zip file containing Xamarin Studio Launcher.app:

Download Xamarin Studio Launcher v3

Smarter Xamarin Android Support V4 / V13 Packages

| Comments

If you’ve ever built an Android app, you’ve probably used the Android Support libraries. Google created these as a way to enable developers to use new features on older Android versions. The most common Support library is arguably Support-v4, however as older Android devices retire and newer versions of Android increase in market share, Support-v13 is becoming more commonplace.

Warning: This is going to be a bit geeky of a post. If you don’t want to know the details, skip down to the TL;DR section for the need-to-know bits :)

Finding Your Android App’s MD5 or SHA1 Signature From Your Keystore

| Comments

If you’ve ever used Google Maps or Amazon App Services in your Android app, you’ve probably gone through the pain of having to find an MD5 or SHA1 signature to give to the service so they could generate an API Key for you.

If you haven’t been through this experience, let me assure you: It’s painful, tedious, and annoying.

What Are App Links?

| Comments

So there’s this new thing called App Links. It’s backed by Facebook and some other big names, so you know it’s going to gain at least a bit of traction. But the problem is, everyone seems to have a hard time figuring out what they actually are and do. The video on AppLinks.org sort of helps, but it still left me confused, even after watching it a few times.

Here’s my attempt to explain what App Links are, why you would need or want them, and how they work. A word of caution: this post is aimed at mobile app developers, so it may be a bit confusing if you’re not familiar with some of the concepts of mobile app development.

Such Android API Levels, Much Confuse. Wow.

| Comments

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

iTunes Media HotKey Disabler

| Comments

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.

iOS7: Fun Times With the New Full Screen Layout!

| Comments

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:

iOS7 Recipe: Background Fetching

| Comments

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:

1
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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

| Comments

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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!