Thursday, November 13, 2014

How to add a Twitter feed to your App Studio app

I've recently released an app for the UK based charity Toilet Twinning. I wholeheartedly encourage you to support the work they do and twin your toilet now. This post is based on lessons from building that app.

The app started life in App Studio but I wanted to add the ability to show tweets from a specific account in the app. I was surprised that this functionality wasn't built in. I was further surprised that there wasn't good documentation anywhere to help add it.
This post is an attempt to address this and show how to add a twitter feed to an app studio app,

Screenshot of the "Toilet Twinning" app showing items from the twitter feed

If you've looked into trying to do this before you may have discovered that there is a video recorded as Build that shows a way of doing this. You'll find it at http://channel9.msdn.com/Events/Build/2014/2-565 The downside of this is that it is more complicated than I needed and only a small amount of the code is available (at
http://blogs.msdn.com/b/rido/archive/2014/04/25/app-studio-build-session.aspx).


The following uses no third party libraries and is done entirely in Visual Studio. It allows adding a list of tweets by a named user to be displayed in the app without requiring a user to log in. If you wanted it to display a search term, such as a hashtag, then minor modifications would be needed but they aren't documented here.

The twitter API requires that all requests are from an authenticated source. While you may typically have a user authenticate, in this case the app is the what is authenticated, using Application-only authentication. This provides access to limited API methods but is sufficient for our needs. If you wish to know more see https://dev.twitter.com/oauth/application-only

To integrate with Twitter you first need to create an app entry on the Twitter website.

  • Go to https://apps.twitter.com/
  • then click "Create New App"
  • You can add any website value if you don't a suitable URL right now. Just remember to come back and replace it with the Store link later.
  • You don't need to enter a callback URL.
  • After accepting the terms and creating the app entry, go to the "Keys and Access Tokens" tab.

This is where you'll get the values for the "Consumer Key" and "Consumer Secret". You'll need to add these to TwitterDataSource.cs later.
Leave the permissions as "Read-only".

Please note that the values in this image are no longer valid for anything. Don't waste your time trying to check for security holes. They are for an app entry that no longer exists and won't work. ;)


We now need to modify and add some files to the solution. You'll find all the changes at https://gist.github.com/mrlacey/1cd1f7a0049c69eb774f but we'll also step through all the individual changes.


To add the details to both the Windows and Windows Phone project we need to add or modify 10 files:

1. Firstly we need a ViewModel to handle the retrieval of data and passing it to the view. Create AppStudio.Shared\Views\TwitterViewModel.cs (from here).

2. The ViewModel has to get the data from somewhere so next we need get the data, so we a data source.  Create AppStudio.Data\DataSources\TwitterDataSource.cs (from here)
It is in this file where we need to set the three constants that are used. The first is the username of the account you want to show the tweets from. The next two are the application API values highlighted above.


3. The data source needs something that will provide it with the data from the twitter API. Create AppStudio.Data\DataProviders\TwitterDataProvider.cs (from here)

4. The provider will return a collection of strongly typed objects. So we need to define the schema of that object. Create AppStudio.Data\DataSchemas\TwitterSchema.cs (from here)

5. Now we've got the data back from Twitter and into our ViewModel we need to tell our MainViewModel about it. Update AppStudio.Shared\ViewModels\MainViewModel.cs with the instructions here.

6. We now need to think about how the data will be displayed. We'll be using resources to define the templates we use in the views. We need to add a reference to the shared app resource (AppStudio.Shared\App.xaml) as defined here.

Let's update the Windows Phone project first.

7. We need to add a new hub section to the main page (AppStudio.WindowsPhone\Views\MainPage.xaml) that will look like this.

8. Then we need to add the resources we defined in the shared project and use in the new hub section. Create AppStudio.WindowsPhone\Views\DataTemplates\TwitterViews.xaml (from here)

Now let's update the Windows project.

9. Again, we need to add a new hub section to the main page (AppStudio.Windows\Views\MainPage.xaml) that will look like this.

10. Finally we need to add the data templates used by the view. Create AppStudio.Windows\Views\DataTemplates\TwitterViews.xaml (from here)


And with that we're done.



An important point to note is that when submitting your app to the store and using the above code, there is an extra consideration you need when submitting the Windows version.
In the cryptography section there are specific declarations you must make as credentials are encrypted and passed over SSL to authenticate with the Twitter API.

Assuming you're not doing anything else involving encryption then you just need to select "Yes" for both questions. Check the box if you can confirm the distributability of your app as asked. If you have other encryption in your app or questions about the legal consequences of using encryption in your app then seek appropriate legal advice.

An important note if you want to update this code and change what or how it's displayed.
As part of the terms and conditions of using twitter and integrating it within your app there are specific requirements about how you display a tweet. You'll find these at https://dev.twitter.com/overview/terms/display-requirements. Consider these carefully before you decide to modify how individual tweets are displayed.


Additionally, if you're interested in improving App Studio apps in other ways you should check out this related blog post.


Making an App Studio app better

I've recently released an app for the UK based charity Toilet Twinning. I wholeheartedly encourage you to support the work they do and twin your toilet now. This post is based on lessons from building that app.

The Toilet Twinning apps were built using App Studio. In the past I've been very critical of apps built this way as most of the ones I've seen have been of what I'll politely call a "less than perfect" quality. Evaluated against some of the older store requirements (that were originally intended to improve app quality but have since been removed to simplify the submission process) many of these apps would not get into the store.

Here's a list of things I did to improve the apps. Hopefully, if you're building an app with App Studio, you'll be able to apply some of these changes to your apps and improve them too.
  • I originally included an Instagram section in the app to show related images. Unfortunately the search functionality stopped working shortly so I removed the related pages and hub sections.
  • The Windows Phone app did not include scaled versions of the images in the assets folder. So I added them to get a better visual experience on phones with larger screens.

  • In the Windows app it didn't include a placeholder for the 310x310 logo image. But it did include them for all other logo images. So I added it and was therefore able to support all tile sizes.
  • I had to remove the, pointless, default tile updating behaviour which just replaces the tile image with the one from Shared/Assets/DataImages/FlipSquareTile.jpg. All this did was replace one image with another. Always the same one and with no extra information. Updating a live tile with new information as it becomes available can be a great thing to do. But this didn't do that. I've made a note below that adding a background agent to have some useful, new, information added to the live tile would be a great future enhancement to the app.
  • Added a placeholder for images in the list while they are loading or to be displayed if there is an item without an image.
  • Replaced the trivial default caching behaviour. What good is a caching data provider that when it tries to refresh and there's no network connection it deletes the data it does have and so shows nothing? Or a cache that only keeps data for 2 hours even if it is updated much less frequently. I replaced the caching behaviour with something smarter. It now keeps older data for much longer by default. It will always show data if it has some, even if it's not able to load any new data. 
  • I've also simplified the logic around attempting to load data. Always loading data every time that the user navigates back to the main page seems like overkill. Open app > Load data > tap on item > tap back > reload all data > tap on item > tap back > reload all data (again) > tap on item > tap back > reload all data (yet again). It seems a bit unnecessary. Loading only when it's likely to have changed seems much more sensible. I opted to do this only when the user returns to the app. OnNavigatedTo in MainPage now contains this:
    await MainViewModel.LoadDataAsync(e.NavigationMode != NavigationMode.Back);
  • Thinking about offline support. I added an indicator when there is no network connection available. After all, if there's a good reason why the app can't load any new data it makes sense to let the user know.
  • On each of the hub sections I moved the progress bar used to indicate network activity/loading so that they appear above the items, not behind them.

  • The default formatting for the blog template that I chose was poorly designed such that the right edge of text was clipped. See in the green rectangle below.
In that I want the text being displayed to actually be readable by the person using this app. I fixed this issue with widths and margins. I also adjusted the spacing and margins so that an extra line of text is visible. It now looks like this:

  • When looking at an individual item from the blog / RSS feed there were other improvements to be made. The original output from the tool looked like this:
But with a few changes was made to look like this:
There are 5 changes here: made the system tray transparent; removed the unnecessary and not fully visible app logo and title; reduced page margins; reduced paragraph spacing; and increased the size of the image. There's more that can still be done with RSS content formatting but this is a definite improvement
  • There was also a subtle issue I fixed that is experienced when swiping between stories/items. If there are multiple items that are long enough to be scrolled and one is scrolled down. Then if you swipe to the side 4 times you will find that you get to an item that is not at the top but already partially scrolled. Almost certainly not what you want but easy to fix. Every time the selected item in the FlipView is changed, walk the visual tree to find the ScrollViewer and have it scroll back to the top (VerticalOffset = 0).
  • On the Facebook hub section there was again more work to be done to tidy up the margins, spacing and text formatting and clipping of text on the right and bottom edges. This is not ideal:
It also doesn't make sense to trim the title at the expense of body detail content. This looks much better:

  • For the Facebook details page, similar changes were made as for the blog details page.
  • On the YouTube hub section there was again a need for a bit of finessing of the basic layout but there were two bigger issues. Firstly, even though a large image is used in the item template the image displayed is actually very small and scaled up leading to a blurry image being shown.
Fortunately the details that the YouTube API returns include a variety of images at different sizes. With this knowledge I changed the code so that it uses the largest thumbnail image available, not just the first in the list. This lead to no blurring in the image (click to view full size)

  • The second big issue I had was that the search for my desired search term "Toilet Twinning" was returning some completely unrelated item. After a little exploration I realised that this was because the search term wasn't being used in quotes. This meant that the server was also returning videos that match on the individual words also. As I don't want to show general videos about twinning (or toilets), it's necessary to make sure the term is encoded in quotes. Unfortunately the web site doesn't allow this.
As it seems that encoding values entered in a URL is too much for I manually edited YoutubeDataSource so it now includes
private const string _url = @"https://gdata.youtube.com/feeds/api/videos?q=%22toilet%20twinning%22&orderby=published&start-index=1&max-results=20&safeSearch=strict&format=5&v=2";
  • Again the YouTube details page needed some refining. The strangest being the removal of the hard coded string "Detail" at the top of the page. I can only assume that this was there as the result of an error in App Studio.

  • I added another hub section to show the tweets from the @toilettwinning account. For details of this see the link at the bottom of this post.
  • The final hub section originally contained HTML content. I replaced this with the direct XAML equivalent as the HTML version prevented horizontal swipes from navigating the hub control. This could be frustrating for users as they swipe through the hub but find the the gesture they're doing suddenly stops working.
  • Many of the above changes shown in the Phone app were also made in the Windows one.
  • Additionally, in the Windows app I removed space reserved for back button on the main page - as the back button will never be shown there
  • On the Facebook detail page in the Phone version, it originally used a purple colour for hyperlinks. This was sometimes very hard to read on the background so I changed it to be white like in the Phone version.


That's not the end though. There are still other things that can be done to improve the app further.
Here are some ideas:

  • Default data for when first run and a better first run experience
  • Add a FAQs page directly within the app to explain more about the charity without needing to redirect to the website
  • Add a background agent to update the tile so new content can be seen without having to open the app
  • Add image caching so that images can be viewed with the other offline content.
  • Improve the HTML parsing to improve the display of content
  • Improve the display of images to better scale and stretch images with consistency but still coping with the variety of images sizes to display.
  • And probably many more things. Got any suggestions?


Hopefully I'll be able to add at least some of these to the app soon.


If you're building an app with App Studio and wish to add a Twitter feed to it, I have another blog post that explains how to do this.


Combining app development and trying to make the world a better place

For a long time, I've been thinking about how app developers, myself in particular, can do more to help make the world a better place. Building apps is all well and good but I often feel that simply having more apps in the various app stores isn't really helping anyone.
Couldn't we do more to help make the world a better place?

It's a potentially noble but quite a grand goal. So I decided to try and simplify things a bit and trying to do something with my limited free time and the other projects I have on at the moment.
Realising there are many organisations already doing lots of fantastic work to help make the world a better place, my thoughts turned to supporting them rather than trying to start something all by myself.

In terms of supporting a charity through app development I see three available options:
  1. Build an app that directly supports the work
  2. Build an app that makes money that can be donated
  3. Build an app that raises awareness
Option 1 could be appropriate if directly tied to the work of an organisation. For example, this may be appropriate if having people look at images to identify patterns or objects or by using the processing power of the device to perform work that helps the charity directly. Such effort requires working closely
Option 2 is best suited to games. Not being a game developer I passed on this option.
This left me with option 3.
But which charity to support?

A few years ago I was working for a company and our office was in a large building housing many other companies. Our office was in one corner of the floor and the toilets were at the far side of the building. To get from my desk to the toilet meant going through seven doors, two of which were security controlled and required an electronic key to get through. A first world problem I know, but this really bugged me.
At least it did until I heard about Toilet Twinning.


When 2.5 Billion people don't have access to a toilet I felt bad about complaining about the minor inconvenience I experienced when I had to go.
Rather than just striving to not feel bad about my first world problem I wanted to do something practical to help and remind me of the fortunate position I'm in. So I twinned my toilet. I got this nice certificate and they got funds to "enable people living in poor communities to have clean water, a decent toilet, and to learn about hygiene – a vital combination that prevents the spread of disease, reduces the number of deaths among children, and brings hope for the future."

Here's the certificate, resting on the toilet I twinned.

It's something I should have been aware of more as I'd used the statistic that more people have mobile phones than access to a toilet in talks I've given in the past.

So, when it came to me thinking about which charity I'd like to help raise awareness for Toilet Twinning were my first thought.

Wanting to be respectful of IP and copyright and not wanting to use someone else's brand without permission or potentially duplicate anything they already have planned I contacted them (via their website) to see if they were happy for me to build something.
To be honest I wasn't expecting a response. If one came I could probably fit in the work around other projects and if I got no response then I'd have eased my conscience for a bit.

However, a few weeks later, when I got back from the Native Summit conference, all fired up by the talk by Mike Lee about developers doing more to improve the world and not just building more and more apps, I had an email from Toilet Twinning saying they were happy for me to build them an app. Taking this as a well timed sign as something I should get off my butt and do. I have.

I've found a bit of time over the last few weeks to fit this in and the apps are now available in the Windows and Windows Phone stores. See links below.

This story doesn't stop there though. If you know me or have read this blog for a while though, you may know I don't just want to make great apps myself, I want to help others build better apps also.

With this in mind, I wanted to combine building the Toilet Twinning apps with doing something that could help other developers improve their apps too.

Having been critical of apps built with App Studio in the past I took this opportunity to use it to build the base of the apps and then document all the issue I found (that many developers simply ignore) and how I addressed them so that others can improve their App Studio built apps too. I have a blog post explaining all this here.

In using App Studio to build an app that aggregates data from external sources, most of which are social networks, I was surprised to see that integration with Twitter was not supported. As I wanted this and I suspect many others would use it if it was available, I have also created a blog post that explains how to add twitter integration to an App Studio app and this is available here.



Get the apps now


and




Monday, November 03, 2014

Amazon are willing to pay £5 for details of my Facebook friends

<JustWondering>
I got this email last week:


Glossing over the fact they ignore our 16+ year relationship and can only address me as "Amazon.co.uk Customer".
I don't think I can recall another business being so transparent about how much access to my Facebook data is worth.

Exactly what data?
We'll, here's what they want to know:



So, that's my details, plus my friends details, their birthday's and their likes.

Wow. At the very least, Amazon think they can make more than £5 extra in profit by being able to remind me that my friend has an upcoming birthday and suggesting things I can buy for them as a gift.
Plus many more things as well no doubt.

Yes, there's a potential benefit of potentially improving relationships by helping make sure I don't forget a birthday and making it easier for me to give (send?) them an appropriate gift based on their likes.
However:

  • Do I really need yet another service sending me emails about peoples upcoming birthdays?
  • Am I really likely to need the present suggestions for my close friends?
  • Based on Amazon's ability to mine large amounts of data, what will be the long term consequence of me giving them this Facebook access?
  • Is £5 really enough to get lots of people to sign up to this? If not, then I wonder how much would be?
  • Do people look at an offer like this and think about the data security implications? Or do they just think "free money"?


</JustWondering>