App Shortcuts in Xamarin on Android 7.1

With the Pixel release, Android 7.1 is upon us and it’s never too early to start playing with some new features!

Xamarin.Android App Shortcuts in Android 7.1
Xamarin.Android App Shortcuts in Android 7.1

One of the features I’ve been looking most forward to is App Shortcuts (previously known as Quickcuts).  This is basically Android’s equivalent to 3D Touch Quick Actions on iOS.

While technically, the Google Now and Pixel Launcher will only support this feature as of 7.1 and higher, a number of other launchers have already added support for App Shortcuts without the requirement of the latest version of Android.

According to Google’s official App Shortcut documentation we can create static and dynamic shortcuts.  This post is going to focus on static shortcuts since at the time of writing, we are waiting on a Xamarin update to provide us with the new API’s for creating dynamic shortcuts.

Static Shortcuts

Static shortcuts are declared in a resource file and can’t change.  They will always show up the same in your app’s list of shortcuts.  For many apps, this is incredibly useful and will probably be what you primarily use.

1. Trick the Manifest

To get started, until Xamarin.Android is updated to support API Level 25, we’re going to have play a small trick on our manifest.

In the application element of your AndroidManifest.xml change, or add a android:targetSdkVersionattribute to have a value of 25.

2. Declare your shortcuts

Static shortcuts are created in an xml resource file.  Typically you’ll create a file: Resources\xml\shortcuts.xml.  The format is pretty simple:

<?xml version="1.0" encoding="utf-8"?>  
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">  
  <shortcut
    android:enabled="true"
    android:icon="@drawable/icon"
    android:shortcutDisabledMessage="@string/shortcut_disabled_msg"
    android:shortcutId="shortcut-id"
    android:shortcutLongLabel="@string/shortcut_long_label"
    android:shortcutShortLabel="@string/shortcut_short_label">
    <intent
      android:action="android.intent.action.VIEW"
      android:targetClass="com.mypackage.ShortcutActivity"
      android:targetPackage="com.mypackage" />
  </shortcut>
</shortcuts>xm

You can declare multiple shortcuts in the same file.

Your shortcuts can also each include multiple <intent .. /> elements which will be used as the back stack for when your user launches the shortcut.  The last <intent .. /> in the list will be the one the user sees when they launch the shortcut.

3. Make sure your targetClass is correct

In case you didn’t already know, by default in Xamarin.Android your activities will have their java generated counterpart code named with a hash prefix (for reasons we are not going to dive into in this post).  This means that figuring out the correct targetClass to use in your shortcut intent declarations may not be as simple or obvious as you would expect.

Luckily, there’s an easy work around.  In your [Activity] attribute, you can specify the java generated class name explicitly by specifying a Name property.  You’ll need to give it a full package name and class name, for example:

[Activity (Name="com.mypackage.ShortcutActivity")]
public class ShortcutActivity : Activity
{
    // ...
}

4. Map the shortcuts.xml to your Main Activity

Now that you’ve created a shortcuts xml resource file, you need to relate it to your app’s activity which is marked as the Main Launcher.  We can do this by adding a simple MetaData attribute to the activity:

[MetaData("android.app.shortcuts", Resource = "@xml/shortcuts")]
[Activity(MainLauncher = true)]
public class MainActivity : Activity
{
    // ...
}

Now you’re ready to install your app and test out your App Shortcuts!  That’s all there is to it!
quickcuts-demo

PushSharp 3.0 – The Push Awakens!

PushSharp 3.0Some of you may be familiar with a little library called PushSharp.  If you’re not, it’s a C# library that helps developers send push notifications to various platforms.  I started this effort a few years ago, and somehow during those years, seemingly despite my best effort, this thing became fairly popular.

Now, more recently (ok-ok, for the last year at least), PushSharp has been sorely neglected.  It still works for the most part, especially if you fork it and merge in some of the open pull requests to improve it like the many others that have already done so, but it’s old, it’s out-dated, and it needs some love.

Continue reading PushSharp 3.0 – The Push Awakens!

Would you like some C# in your Cake?

Cake C# Build DSLI will not blog about food.  I will not blog about food.  I will not blog about food…  but I really like cake!

Ok, all cheese (also delicious) aside, Cake is a “cross platform build automation system with a C# DSL to do things like compiling code, copy files/folders, running unit tests, compress files and build NuGet packages.”.  Although I think by now it’s plenty more than that as well.

If you’ve never heard of Cake, go to the website now: http://cakebuild.net/

I’ve been using/contributing/evangelizing cake for a little while now, and I’m going to share some of my reasoning, my experiences, and some things to keep in mind for practicing safe cake consumption.

var target = Argument ("target", "Default");

Task ("Default").Does (() => {
    Information ("Mmm {0}", "cake!");
});

RunTarget (target);

Why yet another DSL for build tasks?

There’s make, there’s rake, fake, nake, and probably more by now.  In truth, I have nothing against any of these options, they just aren’t quite the right fit for me.

You see, it was getting to the point where Makefiles were getting out of control for some of the projects I was working on.  I’m not a make guru by any means, which surely did not help, but I was also lacking a build solution that was more cross-platform friendly.

I started looking at alternative solutions.  Rake is a common one but I’m not that comfortable with ruby.  Fake was an obvious choice for a .NET developer, and a good way to learn F#, but I’m not sure I (or the other C# developers on my team) wanted another learning curve just to get our actual work done.

I noticed a little effort called Cake.  Heavily inspired by Fake, running on true C# code, geared towards the types of projects we work on.  It immediately captivated me.

Cross Platform

I mentioned that cross-platform was important to me.  When I first discovered cake, it unfortunately did not run on Mono.  While eventually the same Roslyn back-end that Cake uses with the MSCLR should work just fine on mono as well, it meant needing to contribute a bit of code to help cake run under the Mono script host in the meantime.

This is done, it works, and while it may not be perfect, it’s pretty darn close – certainly good enough to be very usable!

There are some other minor issues here and there, but mostly unrelated to cake itself, and more-so other tools not being very portable (I’m looking at you, nuget!).

All things considered, I use cake primarily on OSX running on Mono, and as a great side-effect, it runs on Windows too!

Tasks, Dependencies, etc.

I mentioned cake was heavily inspired by F#, and at its core uses the same concept of tasks and dependency chaining.

In your script, you can define many tasks.  You can make them depend on one another so that when you run a specific task it will automatically walk through the dependency chain and run those as well.  Here’s a pattern we commonly use:

var target = Argument ("target", "libs");

Task ("externals")
    .WithCriteria (!FileExists ("./externals/file.zip")
    .Does (() =>
{
    DownloadFile ("http://site.com/file.zip", "./externals/file.zip"); 

    Unzip ("./externals/file.zip", "./externals/");
});

Task ("libs").IsDependentOn ("externals").Does (() =>
{
    NuGetRestore ("./source/Code.sln");

    DotNetBuild ("./source/Code.sln", c => c.Configuration = "Release");

    CopyFiles ("./**/*.dll", "./output/");
});

Task ("nuget").IsDependentOn ("libs").Does (() =>
{
    NuGetPack ("./Code.nuspec");
});

RunTarget (target);

Aliases, helpers, addins

The power of cake comes from the wealth of Aliases that are available to use in your build scripts.  There’s simple aliases for MSBuild, NuGet, NUnit, File/Directory operations, Compression, and even HTTP.  Things like building a .NET project come down to a few simple commands:

It’s also extremely simple to create your own addins to use with cake.  I’ve made several already myself:

Addins are included in your script with a simple preprocessor directive:

#addin "Cake.Xamarin"

Addins specified like this will automatically be downloaded from NuGet when the script is pre-processed.

Everyone can have Cake

Cake is building momentum.  It’s currently available to install via homebrew on mac, coming soon to Chocolatey on windows, already supported with syntax highlighting in Atom, with omnisharp support coming soon as well.

It’s just C#

Did I mention cake is simply c#?  That’s right, nothing really special here, the only non-standard part about it is a couple of the preprocessor directives.

This means that for the most part, you can do anything with it you could do in standard C#.

We’ve leveraged this to make some of our build scripts more object-oriented so that a lot of the script code can be reused within many different projects.  In terms of lines of code, we’ve reduced the number of build script lines to probably less than one-third what they were in makefiles!

The other big benefit to our team is that everyone on the team knows C#, so they can all actually understand how our build scripts work.

Learn from my mistakes

There are a couple of things I’ve learned about cake that I learned the hard way, so you don’t have to.

  1. FilePath and DirectoryPath are your friends, do not fight them.
    When I first started using Cake I worried too much about file and directory paths and treated them like strings with great paranoia.  What I’ve learned is you need to use FilePath and DirectoryPath as much as you can.  They will keep your code cross platform.  They also have implicit conversions to strings, so you don’t have to explicitly instantiate them to use them, just use the string value.  Trust me on this one, these guys are your friends.
  2. More files isn’t necessarily better.
    We had a tendency to maintain a LOT of makefiles that referenced other makefiles that called targets in yet more makefiles.  Initially I tried reproducing this pattern in cake, and it was not ideal.  Consider adding parameters to invoke certain actions with certain values in a single cake script instead of adding many script files.
  3. Contribute, and make Addins!
    The project leaders of Cake are awesome!  They happily accept quality and sensible contributions and are just generally nice people!

It’s also silly easy to make your own addins, and best of all, with some xml comments and a PR to Cake, you can have your own addin api documentation generated and displayed for you on the official cake documentation site!

Have your cake, and eat it too!

Hopefully I’ve enticed you to try some delicious cake!  Of course cake isn’t for everyone, some people favour other desserts or foods entirely.  But if you’re a C# developer, looking for a familiar build system dsl, I encourage you to try some cake today!

CyanogenMod for your Xamarin apps

CyanogenMod is an aftermarket Android firmware which keeps growing in popularity. With the first release of their platform SDK, it’s now possible to harness the power of the Quick Settings pulldown menu in your own apps running on CyanogenMod.

Quick Settings Custom Tiles are a great way to add an easy, global way for your users to do things like toggle a feature of your app on and off.

Adding a Quick Settings Custom Tile to your Xamarin.Android app is easy now with the new CyanogenMod SDK Component on the Xamarin Component Store.

After you’ve added the component to your project, you can use the CustomTile.Builderto build your tile:

var customTile = new CustomTile.Builder (this)
    .SetOnClickIntent (pendingIntent)
    .SetContentDescription ("Monkey Toggler")
    .SetLabel ("Monkeys " + States.Off)
    .SetIcon (Resource.Drawable.ic_launcher)
    .Build ();

Once you’ve created your custom tile, you can publish it with the CMStatusBarManager:

CMStatusBarManager.GetInstance (this).PublishTile (CustomTileId, customTile);

The CustomTileIdis a unique ID associated with your tile. When you publish a new tile with the same ID, it will update the existing tile under that identifier. This makes it possible to change the appearance based on the current state of your app.

Don’t worry if your app isn’t running on CyanogenMod, in that case the SDK gracefully fails. You won’t see any exceptions, but rather, no Custom Tiles will be published on platforms which do not support it. You can feel safe in adding this feature to your app!

This is the first and only feature that CyanogenMod has released in its Platform SDK. I’m excited to see what new features they add in the near future! Go grab the component today and give your CyanogenMod users a greater user experience!

Improvements coming to Xamarin Google Play Services

<Update when=’June 22, 2015’>

It’s been a month since I blogged about upcoming Google Play Services changes, and a lot has happened since then 🙂

Google released yet another version of Google Play Services (7.5) so we’ve accounted for this update.

We also spent a lot of time on QA this time around, running the updates against many existing applications and samples that we have, and we are moving to a more automated build system that will allow us to release more quickly going forward.

Finally, we re-evaluated some breaking changes we had planned to make and decided that although they would be nice to haves, they were simply not worth breaking so many code bases. We’ve reverted some of these naming changes at least for the near future, so incorporating the update in your app should be pretty simple.

Rest assured, all of the improvements we made that didn’t break existing applications have been kept, so the future still looks great for Google Play Services on Xamarin.Android!

</Update>

Google Play Services is a rapidly evolving library that Google has been using to combat fragmentation on the platform, and ensure their developers have access to great new API’s without having to worry about what Android version their users are actually on.

The rate at which this library has evolved recently has been especially challenging for us to keep pace with in getting bindings out for Xamarin.Android, but, rest assured, we are committed to bringing out a great Google Play Services experience in your Xamarin apps. Here are some of the improvements we’ve been making that are now available as pre-release!

Continue reading Improvements coming to Xamarin Google Play Services

New and Improved Xamarin Studio Launcher

UPDATE – Nov 29, 2016: By popular demand, I’ve created an update which is compatible with both Xamarin Studio and Visual Studio for Mac.  It’s now called MS Solution Launcher and can be found on GitHub (source code and binary release).

Go Check out MS Solution Launcher on GitHub!

UPDATE – Sep 27, 2016:  There’s a new version that I had forgotten to share from some time back which works with the newer versions of Xamarin Studio.  Enjoy the updated download link at the bottom of the post 🙂

UPDATE – Jan 12, 2015: Thanks to the wonderful @Vaclav, Xamarin Studio Launcher now has a proper icon! Please download the much prettier v4 at the end of this post!

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!

Continue reading New and Improved Xamarin Studio Launcher

Smarter Xamarin Android Support v4 / v13 Packages

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 🙂

Support-v4 can be used all the way back to Android API Level 4 (Donut – 1.6), but Support-v13 is only compatible back to API Level 13 (Honeycomb – 3.2).

The challenge with these two support libraries is that they are mutually exclusive. That is, you can’t have Support-v4 and Support-v13 referenced in the same app.

There’s a good reason for this though: Support-v13 actually contains all the code and classes that you’d find in Support-v4, it just adds a bit more on top of them. So, the answer is, just use Support-v13 if you need to instead, right? If only it were that simple.

Trouble in Paradise

Since Support-v4 is so prevalent in apps and provides so much to developers, a lot of third party libraries themselves reference it. Facebook, and even Google Play Services both depend on Support-v4, for example.

Usually 3rd party libraries choose to depend on Support-v4 and not Support-v13 so that they can be used in apps with older API levels.

In the Xamarin world, these libraries (or bindings) are compiled to expect a reference to Xamarin.Support.v4.dll, and if you try and add Xamarin.Support.v13 to your project, things blow up (since Support-v13 already contains Support-v4). This has proven to be painful for developers wanting to use the new Support-v13 features, but also any 3rd party libraries which reference Support-v4.

TypeForwardedTo the rescue!

Luckily, fellow Components Team member Matthew thought up a crafty solution to this issue. There’s a somewhat little known Assembly level attribute called TypeForwardedTo. This nifty attribute allows you to forward an expected type declaration in a given assembly to an actual implementation of it which exists in another assembly.

So, what we’ve done is created a Xamarin.Android.Support.v4.dll assembly which contains nothing but [assembly: TypeForwardedTo (..)] declarations to forward all of the expected Support-v4 types to Xamarin.Android.Support.v13.dll instead.

This means if you’re using a library which requires a reference to Xamarin.Android.Support.v4.dll (Let’s say Google Play Services for instance), you can swap in this ‘type-forwarded’ assembly, and then add a reference to Xamarin.Android.Support.v13.dll as well. Since v13 contains all the implementation which v4 has just forwarded to it (and then some), you can use the new v13 fanciness in your app, while still satisfying the v4 reference that 3rd party libraries are depending on!

Sprinkle in some magic NuGet dust…

This wouldn’t be nearly as fun if you had to worry about which Xamarin.Android.Support.v4.dll you needed to pick (the actual implementation, or the type-forwarded one). Luckily, in addition to the TypeForwardedTo magic, we’re adding some NuGet pixie dust to the mix!

If you’re interested in the mechanics, this is essentially the new .nuspec file we’re using (You can skip ahead to the TL;DR section below otherwise):

<?xml version="1.0"?>
<package >
  <metadata>
    <id>Xamarin.Android.Support.v4</id>
    <title>Xamarin Support Library v4</title>
    <version>20.0.0.4</version>

  <!-- Ommitted boring parts -->

    <dependencies>
      <!-- Depend on v13 support nuget if targeting equal or higher than Android 3.2 -->
      <group targetFramework="MonoAndroid32">
        <dependency id="Xamarin.Android.Support.v13" version="20.0.0.4" />
      </group>
    </dependencies>
  </metadata>
  <files>
    <!-- Use Support v4 lib for anything up to Android 3.2 -->
    <file src="V4Xamarin.Android.Support.v4.dll" target="libMonoAndroid10" />

    <!-- Use Support v4 typeforwarded (to v13 types) lib for anything equal or higher than Android 3.2 -->
    <file src="V4TypeForwardedXamarin.Android.Support.v4.dll" target="libMonoAndroid32" />
  </files>
</package>

TL;DR – The need to know bits

We’ve made some minor, but important changes to the Xamarin.Android.Support.v4 NuGet package:

  1. If your app is targeting Android API Level 13 or higher (Honeycomb 3.2), you will automatically get the Xamarin.Android.Support.v13 NuGet package as a dependency.
  2. If your app is targeting Android API Level 13 or higher, you will also get the Type-Forwarded assembly version of Xamarin.Android.Support.v4.dll installed by the NuGet package. This will work in conjunction with and forward all of its types to the Xamarin.Android.Support.v13.dll assembly that gets installed by the v13 NuGet dependency.
  3. If your app is targeting anything below API Level 13 (eg: Froyo, Gingerbread), you will get the good old Xamarin.Android.Support.v4.dll assembly that you’ve come to know and love!

To be clear, yes, we have decided that if you are targeting API Level 13 or higher, and choose to use the Android Support library v4, you will actually be using v13 instead. We decided the very small size increase was well worth the much improved compatibility between your apps and 3rd party libraries.

You can use these new packages today! We will be rolling out updates to our Components to achieve the same results in the near future!

Enjoy!

Unifying Google Play Services

Once upon a time, you may have noticed there were a lot of choices when it came to adding Google Play Services to your Xamarin.Android apps.

Google Play Services Chaos

This was always a bit confusing. Which version should you use for your app? Should you use the version for the highest API level you’re targeting, or the lowest one? The answer wasn’t always clear.

I won’t go into great detail as to why we did this in the past, because the good news is, there have been improvements in more recent versions of Xamarin.Android which have allowed us to unify many of these packages into one!

Starting today, we have simplified Google Play Services bindings into the two following packages (both for NuGet and Component Store):

  • Google Play Services (Froyo)
  • Google Play Services

This mirrors exactly what Google releases to developers: a .jar file frozen in time for Froyo compatibility, and the new, frequently updated .jar file for Gingerbread and above.

Which one do I use?

As a general rule, you should almost always use Google Play Services, unless you have a special need to target Froyo, however given that Froyo is now only 0.7% of devices, you are most likely safe to drop support for it.

There is one caveat: If you are targeting Gingerbread, there will be some classes in Google Play Services that you aren’t able to use while running on Gingerbread (eg: MapFragment). You should take care to avoid using these if you are running on an API Level they aren’t compatible with (Google has documented this). Luckily Google also provides Support* versions of these classes (eg: SupportMapFragment).

Updated & Disabled/Delisted Components/NuGets

Finally, if you have referenced the Google Play Services (ICS) Component or NuGet, you should update it (it will now appear as simply Google Play Services). This also means we have disabled and delisted the following Components and NuGet packages:

  • Google Play Services (Gingerbread)
  • Google Play Services (JellyBean)
  • Google Play Services (KitKat)

If you were using any of those packages, now is a good time to update them to use the new packages!

Finding your Android app’s MD5 or SHA1 Signature from your keystore

Grump Cat does not like keystores
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.

First of all, you need to find out which .keystore file was used to sign your app. This is probably different depending on if you’re running a debug build versus a signed build for the app store.

If you’re a Xamarin.Android user, you may not have even been aware that a debug.keystore file was created for you at some point and is used to sign all of your debug builds, so you can remain blissfully unaware that it exists, or where it even lives.

There’s a great article on the Xamarin Docs Site: Finding your Keystore’s MD5 or SHA1 Signature that shows you how to generate these values step by step. Put aside 15 minutes to go through it though (and hey, I wrote the initial draft of the doc, it’s as short as Google allowed me to make it, I swear!).

Enter, Android Signature Tool.

If you’ve been to my blog, you probably know that I don’t like to complain about problems that I can’t offer a solution for, so today is your lucky day!

Android Signature Tool

I’ve created a little tool called Android Signature Tool (yes, the creative juices were flowing with that one). It’s a simply GUI app (with a GUI for both Mac and Windows) that aims to minimize the tears spent on getting MD5 and SHA1 signatures.

It’s very simple. It will try and first find java’s keytool executable on your machine (which is needed to generate the signatures). The default option is to try and find your Xamarin generated debug.keystore file for you, and spit out the MD5 and SHA1 signatures with the click of a button! You can also specify your own .keystore file (for which you need to know the alias, storepass, and keypass you used when you created it).

Hopefully this tool makes your life just a little bit more simple. Enjoy!

What are App Links?

What are AppLinks?
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.

Let’s find a problem to solve!

App Links solves a problem that maybe not everyone has caught up to yet, or even knows is a problem, or will be a problem for them. Right now, if you were building an app and wanted to link to a Book on Amazon from within your app, how would you do it? You’d probably find the link to the book (let’s say http://amzn.com/B007Q4OVHQ) and simply open that URL in the web browser on the device.

Why-Link-To-Websites-Instead-Of-Apps

Sending your user into the mobile browser to this page is fine, it works, and Amazon even displays it nicely in a Mobile friendly format for you. But is this really the best you can do? What if your user already has the Amazon app installed on their mobile device? They’re already logged in to the app, so the friction of actually buying the book you linked to at this point is much lower than if you had sent them to the website where they may still have to login. Besides, the native app is usually, generally a much better experience. Can’t our users have nice things?

Why are we linking back out to the web? The pieces are all there for a better experience, we just need to put them together!

Technical Hurdles

Ok, so I’ve convinced you, instead of opening the mobile web page for the web link (http://amzn.com/B007Q4OVHQ) it would be much better to open that content right in the native app on the device. Let’s assume the Amazon iOS app has registered itself to handle the URL scheme amazon://. Now, let’s also assume that it’s been designed to accept a URL in the format of something like this:
amazon://content/item?id=B007Q4OVHQ

So for the techies out there, when another app asks iOS to open this URL, since Amazon’s app is registered to handle amazon:// type URLs, iOS will pass the entire URL into the Amazon app when it is launched, instead of trying to open this URL in the browser. At this point, it’s up to Amazon’s app logic to figure out how this deep link is opened inside of the app. Ultimately the app will be programmed to see that the user wants to open the details of an item with an ID of B007Q4OVHQ

This all works fine today as is, and you can certainly do it (at least in theory, I have no idea if Amazon’s app actually supports deep linking like this). But, how are you supposed to know all the details of the URL scheme Amazon uses within their own app? They may not publish this information anywhere, and even if they do, once you implement it for Amazon, what happens when you want to do the same for ebay, and the next site, and the site after that?

You can see where I’m going with this. The process would result in an exhaustive amount of code to handle each site on a case by case basis. It would be a nightmare to implement, let alone maintain.

App Links to the rescue!

Here’s where the App Links standard shines. The idea simply put is that a web link to content should be able to define how that content may be viewed within native apps, on mobile devices.

So, if Amazon were to add a bit of special HTML to the book’s web page (for http://amzn.com/B007Q4OVHQ), instead of trying to figure out how we should construct an amazon:// link on iOS for that content, we would simply scan the content of the book’s page to see if Amazon has told us about any other way to link to this same page’s content in mobile apps on other devices.

Dropping down to a more technical level, this content is defined by using special <meta .. /> tags in the web page’s HTML. For the iOS example we’ve been looking at, Amazon could add something like this to their HTML:

<head>
  <meta property="al:ios:url" content="amazon://content/item?id=B007Q4OVHQ" />
</head>

This would describe the exact URL to use for deep linking to the content from this web page in the Amazon iOS app.

One more piece to the puzzle

This is all great, except you may be wondering, how does a mobile device know about this special metadata in the web page’s HTML? Well, it doesn’t, at least not by default.

The other big piece of the puzzle is getting apps to look for this metadata when they are going to navigate to a URL. It’s not hard to do in practice, but this means every time you navigate to a URL in your app, you will need to check to see if that URL contains any App Link metadata. I’ll leave the debate about how this is good or bad for another time.

On iOS, you would basically replace:

UIApplication.SharedApplication.OpenURL("http://amzn.com/B007Q4OVHQ");

with this:

Rivets.AppLinks.Navigator.Navigate(..)

What this does is instead of directly navigating to the URL, it loads the URL first, checks for App Link metadata, and if it finds it, navigates to the appropriate app URL instead of the web URL.

App Links and C#

See what I did there? Obviously Rivets.AppLinks.Navigator.Navigate(..) is not part of the iOS SDK.

I’ve been working on a C# implementation for App Links called Rivets. If you have read anything about app Links so far, you’ll probably have heard of Bolts which is an implementation of App Links for iOS (obj-c) and Android (java) created by Facebook. So, Rivets is the Xamarin Android, Xamarin iOS, Windows Phone (and hopefully Windows Store soon) equivalent of Bolts!

Other Platforms ahem, Android and Windows Phone

The example we looked at was specifically about iOS, but make no mistake, Android and Windows Phone are along for the ride. I won’t go over the entire specification here, you can visit the documentation for that, but basically each platform has its own specific metadata property tags. So on Android you’d have something like:

<metadata property="al:android:url" content="amazon://content/item?id=B007Q4OVHQ" />
<metadata property="al:android:package" content="com.amazon" />

Windows Phone is included in the standard right now, but sadly Windows Store and Windows Universal are not. I’ve already petitioned to have them supported, though there’s really nothing stopping us from adopting them as part of the standard as long as we are consistent on the keys used (eg: al:windows_store:url and al:windows_universal:url).

Finally, iOS actually has two other more specific targets: iphone and ipad (eg: al:iphone:url). The idea being that you might have different URL schemes for iPad and iPhone apps.

Fallback Plan

You might be wondering what happens when you try to navigate to a page which you presume might have App Link metadata, but it does not, or it does not have it for the platform you’re currently on (Windows Phone apps are still not as common for instance).

The standard for App Links has this taken care of. In the App Link metadata, a Fallback Url can be specified. This way, if the device can’t find any links pertaining to the given device, it may still be able to find a Fallback URL specified by the App Link metadata. In a worst case scenario, if no Fallback URL is found, you can simply load the original web link as you would have before App Links existed. Simple.

In a nutshell

To recap (with an illustration below to help), App Links are simply a standard way for describing how the content in a web page can be viewed, or deep linked to within a mobile app. It’s this standard way of describing such information that allows any app to discover how to deep link to content in any other app by knowing only the web URL for the content you’re interested in linking to.

App-Links-Example-Flow

App Links are open source, accessible to everyone, and work across devices. Will they change the world? I don’t know. But I think they’re a pretty good way to solve a problem that we may not yet be aware of.

I’d encourage you to start adding App Links navigation to your apps today!