Pinned Site Live Tiles belong on all sites

Imagine if you could take your existing website and turn it into an app with minimal effort. Of course, that’s impossible. But you can get 75%* of the way there with an awesome new Internet Explorer feature I recently implemented on one of SEP’s sites called Pinned Site Live Tiles.

What are Pinned Site Live Tiles?

I am sure you are familiar with live tiles. They first came with the launch of Windows Phone and now are a defining feature of Windows 8+ as well. Live tiles allow apps that have been pinned to the user’s start screen to update their tile with dynamically generated and presumably relevant information. Pinned SLTs (which I will now call slivets) bring that feature to Windows 8.1′s IE11 when you pin a web link to the start screen. They basically transform a simple bookmark with a blurry favicon into something almost indistinguishable from a real app. Scott Hanselman wrote an easy how-to guide on his blog.

But things just got better. Nestled deep within Matt Hidinger‘s interesting “[Live Tiles Enhancements](http://channel9.msdn.com/Events/Build/2014/2-523 “MSDN Channel9″)” talk from Microsoft’s BUILD conference was a cool little revelation: slivets work on Windows Phone 8.1 as well as Windows 8.1. So now they work on all of Microsoft’s desktop, tablet, and phone platforms.

A Disclaimer

I guess it’s worth mentioning that slivets only work when IE11 is the default browser. But that limitation doesn’t matter since it won’t affect your target audience. Anyone interested in apps, namely users of Windows tablets and Windows Phones, are almost certain to have IE as their default browser. And frankly, many desktop users never change their default browser away from IE.

The Case for Pinned Site Live Tiles

Slivets work for almost the entire the app-inclined Windows user base and for all of Windows Phone users. This is a large market, and although currently perched at third place in worldwide market share, it is an underserved market too. Some may scoff at the size of this user base in comparison with Android and iOS. But anyone with a great website who wants apps is likely already going the Android/iOS route since they give the most bang for the many bucks it takes to build an app. That leaves just the Windows platforms in need of apps, and slivets fills those exact markets.

You can enable one of the signature Windows platforms’ features just by adding a couple meta tags to your header and a few xml files. Who cares about bang vs. buck when the price is nearly free. In fact, it’s so easy that even if you don’t have iOS/Android apps you should still enable slivets, the same way you would be silly not to include an apple-touch-icon.

From now on, I plan to add slivets to all the websites I build unless it’s unnecessary or technically impossible.

Adding slivets to your site is not difficult, but there are some tricky situations that can waste your time if you don’t know where to look for answers. I’ve included some more technical information and helpful tips in my companion article, “How to create a Pinned Site Live Tile without pain.”

*Disclaimer: invented number.

Creating a Pinned Site Live Tile easily and without pain

The list of things a developer must add to their website is constantly growing. I’m not talking about the big things; I’m talking about the little stuff that would be stupid to leave out. For instance, favicons were introduced by Internet Explorer 5 in 1999 (they made it into the HTML 4.01 recommendation later that year). Your site would function just as well without a favicon but you would be crazy not to have one. It’s basically a requirement. The same thing goes for the description meta tag and apple-touch-icon, among others.

And now there’s another one: Pinned Site Live Tiles as implemented by IE11 in Windows 8.1 and Windows Phone 8.1. Pinned SLTs (which I call “slivets”) allows a website to have a series of beautiful images for the different sizes of Windows tiles and even allows the display of website information using some lovely built-in tile templates using a simple xml schema.

It’s a little more involved than, say, a favicon but it’s really not hard. Especially for the value you get. Microsoft has a lot of documentation to make this easy. What can be hard is finding the right page since it’s not all in one place. Here are some links to help you avoid wasted time and pain.

Quick start

buildmypinnedsite.com - This is the very first place you should go if you want slivets. This easy wizard will get you up and running in no time. You will probably want to replace the images with something more professional and customize the urls to match your site, but it quickly gives you something that’s working and gives you a good place from which to start customizing. It’s basically the File > New of slivets.

Make a Windows 8.1 Pinned Live Tile for YOUR website in minutes – I’m not going to give a complete how-to because Scott Hanselman already has and his is better than mine would be. He walks you through the wizard site above and explains what it all means.

Designing

Create live tiles for your websites in IE11 – This is the jumping off place to explore the Microsoft help for slivets. Start here with questions.

Pinned Sites – This the jumping off place to explore the Microsoft API documentation for pinned sites including schemas for the browser config, for html meta tags, and the complete list of properties, methods and events used by the browser. This is really helpful for pulling off some cool and crazy website-to-slivet interactions with the variety of available javascript hooks.

The tile template catalog (Windows Runtime apps) – You’ll want to pick your tiles to fit the data you are displaying. This is the comprehensive list of all possible tiles with example xml and result photo to get you started. You should find several you like. Of course, you can make the tile look like whatever you want by simply picking the single photo template and generating the custom-formatted image yourself. But that would take more server infrastructure on your end and would risk making your tiles clash with the aesthetic of the OS. Still, the option is there.

Debugging

Build a live tile – This starts out as Microsoft’s how-to guide but important part is at the very bottom under “Testing and finding problems with live tiles.” Slivets are designed to light up with whatever pieces are present and if they aren’t there, fallback to normal behavior. This is really nice for end-users, but it can make development difficult because when something doesn’t work, IE is quite taciturn about reasons. The tips at this link are simple but indispensable.

Fiddler – While we are on the topic of debugging, you pretty much have to have Fiddler to monitor the network traffic. This will tell you if the endpoints you defined are even being hit. I wasted a couple hours trying to solve a seemingly impossible problem with my slivets, but after I used Fiddler I solved the problem in minutes.

If you need any more help feel free to contact me. Of course, if you’d like to talk to someone who actually knows something, I’ve found Microsoft Program Managers MattHidinger and Jacob Rossi to be quick, friendly and very helpful.

Wrestling with CheckedTextViews in an Android Multi-Choice ListView

I was building an Android ListView in an AlertDialog.Builder that allowed multi-choice. It displayed a list of accounts and you could select the one or more you wanted to operate on. I also needed to be able to set certain accounts as checked by default.

Android MultiChooser AlertDialog

I couldn’t use the built in AlertDialog.Builder(context).setMultiChoiceItems() method because it only accepts an array of strings of display data and I needed a custom list item view with the more complex AccountSummary object.

Here is the getView method on my adapter.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    AccountSummary account = getItemAt(position);

    if (convertView == null) {
        convertView = getInflater().inflate(R.layout.account_multi_choice_dialog_item, null);
    }

    CheckedTextView text = convertView.findViewById(R.id.text_view);
    text.setText(account.name);

    // Set the CheckedTextView to checked if its a default here

    return convertView;
}

Everything is standard except for the need to potentially set the item as checked. You would think this would be very simple, just take the CheckedTextView and set it to checked.

    CheckedTextView text = convertView.findViewById(R.id.text_view);
    text.setText(account.name);

    // This does not work
    text.setChecked(account.isDefault);

This does not work. For some reason you can set CheckedTextView to checked for an hour’s worth on mintues in a row (I sure did) but it will never be remembered. In fact, I even tried checking the TextView from the ‘outside’ by accessing the ListView from my activity, grabbing the correct CheckedTextView, and setting checked there. And that didn’t work either.

It turns out, as I understand it, that the ListView maintains the checked state of its list items and ignores the state that item says it should have. The following small change in the code makes everything work charmingly.

    CheckedTextView text = convertView.findViewById(R.id.text_view);
    text.setText(account.name);

    // This, quite charmingly, works
    ((ListView) parent).setItemChecked(position, account.isDefault);

Instead of checking the item, I tell the ListView to set checked on the correct item. According to the Android source, AbsListView keeps all the checked state in a SparseBooleanArray so the checked state in the TextView goes nowhere and has no effect. I’m not sure I understand the full picture, but just set the checked state on the ListView, not the list item.

So now you know.

Using factories for cleanliness in Android testing

I am on a team building a native Android app for a local credit union. We are doing some really cool stuff around testing with unit tests, automated instrumentation tests using spoon, and manual user experience testing. We are working in a low-ceremony, flow-based process with continuous client feedback.

One tool we are using to greatly improve our test quality is factories. Android uses Java and so the very name “factory” on a Java project (for a credit union, no less) is probably making you think of BaseAbstractStrategyBuilderFactoryImpl and such, but such enterprisyness is not the case.

Factory chimneys billowing polution

In reality, factories aren’t obligatorily complex: we are simply building an object. If there was any business logic going on I’m sure it would be more complex, but we’re just using them in tests to make writing, debugging, and understanding them easier. Even with a test-first development flow, many tests end up needing some state setup to run correctly and hit to correct code paths. And state setup is a chore.

Java is fairly verbose. Factories allow us to hide that boring instantiation and assignment snooze-festing in a separate place from the main test function.

Take this example from a bit of code I’ve been working on recently. I’ve added some Arrange, Act, Assert comments to make this easier to follow.

@RunWith(AppTestRunner.class)
public class AccountsListActivityTest extends AppActivityUnitTestCase<AccountsListActivity> {

    public AccountsListActivityTest() {
        super(AccountsListActivity.class);
    }

    @Test
    public void selectingAccountListItemLaunchesAccountDetail() {

        // Arrange account
        Account account = new Account();
        account.id = "checking-account-id";
        account.name = "CHECKING";
        account.isInCashFlow = false;
        account.isFavorite = false;

        // Arrange group
        AccountGroup group = new AccountGroup();
        group.id = "group-id";
        group.owners.add("George E. Meade");
        group.owners.add("Robert E. Lee");

        // Arrange group account
        group.accounts.add(account);

        // Arrange list item
        AccountListItem accountListItem = new AccountListItem();
        accountListItem.build(group, account);

        // Act
        activity.onItemSelected(accountListItem);

        // Assert
        Intent startedIntent = assertThat(activity).launchedActivity(AccountDetailActivity.class);
        assertThat(startedIntent).hasExtra(AppExtras.ACCOUNT, account);
    }
}

Not very thrilling? At least it is straightforward, especially since you can see exactly what state is necessary to build make this action work. But why do we care that you can only build an accountListItem from a group and an account? Why do we care that account.isFavorite is required? “isFavorite = false” is my motto when it comes to this load of excess. All of the necessary state arrangements are clear, necessary, and completely irrelevant to what we’re testing. The boring explicitness makes the thing we care about hard to find. I told you this was a snooze-fest.

I’m going to take all the arrange stuff out and make a private method on my test class to hide all the boring setup.

@RunWith(AppTestRunner.class)
public class AccountsListActivityTest extends AppActivityUnitTestCase<AccountsListActivity> {

    public AccountsListActivityTest() {
        super(AccountsListActivity.class);
    }

    @Test
    public void selectingAccountListItemLaunchesAccountDetail() {
        // Arrange
        AccountListItem accountListItem = setupState();

        // Act
        activity.onItemSelected(accountListItem);

        // Assert
        Intent startedIntent = assertThat(activity).launchedActivity(AccountDetailActivity.class);
        assertThat(startedIntent).hasExtra(AppExtras.ACCOUNT, account);
    }

    private AccountListItem setupState() {
        // Arrange account
        Account account = new Account();
        account.id = "checking-account-id";
        account.name = "CHECKING";
        account.isInCashFlow = false;
        account.isFavorite = false;

        // Arrange group
        AccountGroup group = new AccountGroup();
        group.id = "group-id";
        group.owners.add("George E. Meade");
        group.owners.add("Robert E. Lee");

        // Arrange group account
        group.accounts.add(account);

        // Arrange list item
        AccountListItem accountListItem = new AccountListItem();
        accountListItem.build(group, account);
    } 
}

The setupState() method is still pretty overwhelming, but we can ignore it when we read the test method and that is an instant readability win.

Now comes the point of this article. Since we don’t care about the details of the state setup for this test and the (redacted) others in this class, we can move all this out into a factory that will build the objects we need for us. Now other test classes that will need similar state just say “give me one” and no fuss will ensue. The reusability aspect is really nice. The test is now looking clean.

@RunWith(AppTestRunner.class)
public class AccountsListActivityTest extends AppActivityUnitTestCase<AccountsListActivity> {

    public AccountsListActivityTest() {
        super(AccountsListActivity.class);
    }

    @Test
    public void selectingAccountListItemLaunchesAccountDetail() {
        activity.onItemSelected(basicAccountListItem());

        Intent startedIntent = assertThat(activity).launchedActivity(AccountDetailActivity.class);
        assertThat(startedIntent).hasExtra(AppExtras.ACCOUNT_account, account);
    }
}

In my factory I’ve refactored the state into a few simple, reusable methods that I can mix and match. This arrangement grew out of the needs of the various tests as we wrote them and needed different pieces of data.

public class AccountsFactory {

    private static AccountGroup emptyGroup() {
        AccountGroup group = new AccountGroup();
        group.id = "group-id";
        group.owners.add("George E. Meade");
        group.owners.add("Robert E. Lee");

        return group;
    }

    public static AccountGroup groupWithAccount(Account account) {
        AccountGroup group = emptyGroup();
        group.accounts.add(basicAccount());

        return group;
    }

    public static Account basicAccount() {
        Account account = new Account();
        account.id = "checking-account-id";
        account.name = "CHECKING";
        account.isInCashFlow = false;
        account.isFavorite = false;

        return account;
    }

    public static AccountListItem basicAccountListItem() {
        AccountListItem accountListItem = new AccountListItem();
        accountListItem.build(groupWithAccount(), basicAccount());

        return accountListItem;
    }
}

The Aesop-approved moral to this story is to only put the relevant stuff in the test and hide the rest of the boring state-making in a convenient spot for reuse. On this current project we call them factories, and they work great.

You have to start somewhere

I started fresh in at SEP on Monday and by Tuesday the bananas were fresh out.

Fellow new guy Jackson and I were tasked with our first project on Monday just before quittin’ time: update the internal résumé reporting website from ‘ancient’ to ‘tomorrow.’ It currently runs on a mid-2006 vintage copy of Ruby on Rails (version 1.1.6). We’re supposed to be bringing it up to Rails 4 (coming soon, 2013) but some fundamental pieces of its inner-working were axed from Rails by the end of 2006. We’re not supposed to rewrite the project, just bring it up to date, but many important pieces cannot be upgraded.

Full disclosure: I’m fresh in when it comes to Rails (“never touched the stuff”), so by Tuesday afternoon my brains were fresh out. And, as I said before, so were the bananas.

As we passed through The Commons during the first-day tour, Laura from HR said “there shall be fruit” and, unfortunately, there was no fruit. In my hour of need: fresh out. To quote the great Barney Fife, “Well, Andy, a slender high-spirited person needs a sugar pick-me-up late in the day.” I had to settle for a cup of ice. Just then, something happened…

Chapter 2. Just when hope is almost lost, things start to look brighter for our young heroes.

A remarkable thing about SEP: everyone is willing to help. Not to be too self-critical (and Jackson’s effort, to be fair, was nothing short of heroic), but we needed help.

There are many things I don’t know. Rails is not the only thing on that list. Here are a few others to get you started. I don’t know:

  • The name of the git server (easy to guess)
  • The name of the TFS server (impossible to guess, sounds more like a band name)
  • The name of the database server (easy, but after the TFS server I was expecting anything)
  • The name of the project (five-digit number starting with 06)
  • The name of the guy in the next cube (I love the three-monitor setup)

I also don’t know about many company policies. For instance, do lowly developers need an official sanction from IT to brazenly install Ubuntu VMs on our machines (no). And I haven’t even started on all the questions we had about the résumé website’s architecture and history.

Chapter 3. Sorry about chapter 2, this is where things actually get better.

Matt Swanson. He has worked on the résumé system. We asked him a lot of dumb questions and he gave us a lot of good answers. He helped us a ton and he’s given the project a fresh start.

I would like to give a You Rock™ card to Matt (like they told us about in orientation), but I don’t know where they are.

P.S. For non-SEPeers: if you are given two You Rock™ cards of the same color or one each of both colors, you can turn them in to receive Good Stuff™.