As I have already developed a news reader app for my blog, I got asked quite a few times if I want to share my code to help others creating their apps. As I need to redesign my blog reader to match the latest OS features of Windows and Windows Phone, I decided to create my WordPressUniversal library.
Automattic, the company behind WordPress, integrated a powerful JSON API into their JetPack plugin. My library is based on this API. Please make sure the JSON API is active on the blog you are developing your app for.
The library currently provides the following features:
getting a list posts or pages
getting a list of all categories
getting a list of comments for the site and single posts
supports Windows Phone 8 & 8.1 Silverlight, Windows Phone 8.1 RT, Windows 8, Xamarin.iOS and Xamarin.Android
The library deserializes all data into C# objects you can immediately work with.
It is still a work in progress, but as it provides already a bunch of options to get you started, I am making this public already.
I am constantly working on the library, so be sure to follow the project along.
Note: JetPack’s JSON API does not support guest commenting at the moment. I already reached out to Automattic to (hopefully) find a solution for this. If you cannot wait, Disqus has a portable solution for Windows Phone apps.
During the last months, I used the few times of my spare time when I wasn’t in the mood for programming to read Geoff’s latest book for diving deeper into Azure Mobile Services. Geoff is well known in the community for his Azure experience, and I absolutely recommend to follow him! I am really glad he asked me to review his book and need to apologize that it took so long to get this review up.
The book itself is very well structured with a true working XAML based game that utilizes both Windows 8 and Windows Phone 8 and connects them to one single Mobile Service.
Even if you are completely new to Azure, you will quickly get things done as the whole book is full of step-by-step instructions. Let’s have a quick look on what you will learn while reading this book:
Prepare your Azure account and set up your first Mobile Service
Bring your Mobile Service to life and connect Visual Studio
Securing user’s data
Create your own API endpoints
use Git via the console for remote development
manage Push Notifications for both Windows and Windows Phone apps
use the advantages of the Notification hub
Best practices for app development – some very useful general guilty tips!
I already use a Mobile Service with my Windows Phone App TweeCoMinder. I have already started a Windows 8 version of that app, which basically only needs to be connected to my existing Azure Mobile Service to finish it.
While reading Geoff’s book, I learned how I effectively can achieve this and also improve my code for handling the push notifications on both systems. The book is an absolutely worthy investment if you look into Azure and Mobile Services and has a lot of sample code that can be reused in your own application.
As this is my first book review ever, feel free to leave your feedback in the comments.
After playing around with WP8.1 for a few days (like everyone else), I decided to dig a bit into development of WP8.1.
As oAuth is the common authentication method nowadays for Apps and Websites, I was curios about the implementation of the WebAuthenticationBroker in a WINPRT app.
I used it before with Windows 8 for my TweeCoMinder app, but that’s a few month back (it didn’t make it into the Store yet (another goal, right – porting TweeCoMinder to Universal will be a lot of fun and learning for me ;-)).
Before we continue: This is a pretty huge topic. Be prepared that it may take you more than one time to read and understand what is going on.
Let’s dive into it. Unlike the Windows WebAuthenticationBroker, the Phone version does not use the AuthenticateAsync method. It uses AuthenticateAndContinue instead. This is related to the lifecycle on phone, as it is more likely that an WINPRT app is suspended than on Windows (at least that’s the official reason).
Preparing our App
But we are able to get it working, no worries. First, we need the so called ContinuationManager. This class brings the user back to the app where the fun begun.
You can download the complete class from here (it is a 1:1 copy from the official MSDN reference). The only thing you need to do is to add your app’s Namespace into it.
The next step we need to do: some modifications at the App.xaml.cs file.
1. Add an OnActivated event (it isn’t there in the Phone template) [updated: added missing continuationManager initialization]
protected async override void OnActivated(IActivatedEventArgs e)
{
continuationManager = new ContinuationManager();
CreateRootFrame();
// Restore the saved session state only when appropriate
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
try
{
await SuspensionManager.RestoreAsync();
}
catch (SuspensionManagerException)
{
//Something went wrong restoring state.
//Assume there is no state and continue
}
}
//Check if this is a continuation
var continuationEventArgs = e as IContinuationActivatedEventArgs;
if (continuationEventArgs != null)
{
continuationManager.Continue(continuationEventArgs);
}
Window.Current.Activate();
}
First, we check the SuspensionManager and let him restore a saved state – if there is one. If you do not have a Folder ”Common” with the SuspensionManager, just add a new Basic page. This will generate the Common folder with the SuspenstionManager class for you.
After that, we are checking if the activation is a Continuation. We need this check there, otherwise the app will not be able to receive the Tokens after returning from the WebAuthenticationBroker. Note: declare the ContinuationManager globally in App.xaml.cs with this to avoid multiple instances (which will crash the app for sure).
public static ContinuationManager continuationManager { get; private set; }
2. Add a CreateRootFrame() method with some little changes to the default behavior
private void CreateRootFrame()
{
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame != null)
return;
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
//Associate the frame with a SuspensionManager key
SuspensionManager.RegisterFrame(rootFrame, "AppFrame");
// Set the default language
rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
rootFrame.NavigationFailed += OnNavigationFailed;
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
This simply creates the RootFrame for our app. Place this one in the OnLaunched and OnActivated events. Instead of creating the RootFrame in the OnLaunched method, declare it globally in App.xaml.cs with this:
public static Frame rootFrame { get; set; }
3. Handle the HardwareButtons_BackPressed event
private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
Frame frame = Window.Current.Content as Frame;
if (frame == null)
{
return;
}
if (frame.CanGoBack)
{
frame.GoBack();
e.Handled = true;
}
}
This just handles the BackButton press globally (you can still handle it on individual pages/frames/controls).
4. Handle Navigation Errors in the OnNavigationFailed event
private void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
//change this code for your needs
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
5. Add the Save method to the OnSuspending event
await SuspensionManager.SaveAsync();
This is just to save the current state of our app while the App gets suspended.
Preparing oAuth
Now, we have our app prepared to be continued after the WebAuthenticationBroker has finished. Pretty much to do so far, but now we are going to start with the real fun: The oAuth process. We are going to use Twitter in this case, as it is very popular to be added as a sharing option in apps (yes, I recently saw a lot of them).
Before we are able to connect to Twitter, we need some preparing methods. The first one is to get a random character chain. Twitter demands a 32 digit chain that contains random alphanumeric values, the so called oAuth-nonce. A lot of samples use a chain that is shorter, which will be fine for the initial authentication, but not for additional request. Here is my method:
string GetNonce()
{
StringBuilder builder = new StringBuilder();
Random random = new Random();
char ch;
for (int i = 0; i < 32; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
return builder.ToString().ToLower();
}
We also need a timestamp in Milliseconds, this one is pretty straight forward:
You will find a lot of samples that don’t use the oAuthTokenSecret in the basic method. We will need this for additional requests, so I am using a nullable string overload. This way, I need only one method after all.
Performing the Authentication process
To start the Authentication process, we are using this code in our Button_Click event:
First, we need a RequestToken that authenticates our request for the oAuthToken, that’s why we are awaiting the GetTwitterRequestTokenAsync(TwitterCallBackUri, TwitterConsumerKey) Task. The Task itself is this one:
If you think that’s all of our code, I need to disappoint you. The fun goes on. We prepared our app to be recognized as continued app. To effectifely continue our app, we need to use the ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args) event from our ContinuationManager class:
public async void ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args)
{
WebAuthenticationResult result = args.WebAuthenticationResult;
if (result.ResponseStatus == WebAuthenticationStatus.Success)
{
await GetTwitterUserNameAsync(result.ResponseData.ToString());
}
else if (result.ResponseStatus == WebAuthenticationStatus.ErrorHttp)
{
MessageDialog HttpErrMsg = new MessageDialog(string.Format("There was an error connecting to Twitter: \n {0}", result.ResponseErrorDetail.ToString()), "Sorry");
await HttpErrMsg.ShowAsync();
}
else
{
MessageDialog ErrMsg = new MessageDialog(string.Format("Error returned: \n{0}", result.ResponseStatus.ToString()), "Sorry");
await ErrMsg.ShowAsync();
}
}
The WebAuthenticationResult holds our accessToken and accessTokenSecret, that we are going to exchange for our final oAuthToken and oAuthTokenSecret (we need them for all further requests).
If all goes well, we are now able to call the final Authentication Task GetTwitterUserNameAsync(string webAuthResultResponseData):
At the end of this Task, we will have all Tokens and the ScreenName of our user and can save them for further usage.
The whole oAuth process is a pretty huge thing as you can see. I hope this blog post helps you all to understand how to use the WebAuthenticationBroker and get the required Tokens for all further requests.
Here are some useful links to the MSDN, if you want to dive deeper:
As always, this covers my experience. If anyone has tips or tricks to make this all easier (except of using already existing libraries), feel free to add a comment below.
It was a journey with a lot ups and downs, but I hit the next Milestone as a Windows Phone Developer: 50,000 downloads across all my apps!
You might wonder why I am so happy about that. That’s very easy. I cover very special topics with my apps. For example, I made an app that helps parents to learn the tying of shoe laces with their kids. A very special app, but one that has also some serious background: there are more kids in the age of 2-6 years that are able to use a smartphone than kids that know how to tie their shoes. That was the reason for the app.
Another example is my very first app I ever wrote. After acquiring my fishing license back in 2011, I needed a Fishing Knots app (they are hard to remember as newbie). There was none. As I didn’t even thought about switching to one of the other OS that has such an app, I decided to write it by myself. With literally zero knowledge of programming. That was the beginning of my developer story.
Let’s have a look at my most special app: TweeCoMinder. TweeCoMinder stands for “Tweet Count Reminder” and does the same. If you are watching for special tweet counts like “round” numbers of 25,000 or similar, this app is for you if you don’t want to miss those counts. The app is backed by a Windows Azure Mobile Service that checks if your count has changed. The app has also some other cool features, but you should have a look yourself:
To celebrate my personal milestone, I am making TweeCoMinder free during the Weekend!
While working on my current project, I needed a solution for a running code with a time offset. Well, you might say, no problem after all, and it is true.
The challenge at this point was to find a way to keep it cancelable at any time. And so the fun started.
After digging a bit deeper into the MSDN documentation, the BackgroundWorker class already have a bunch of methods and properties that are very helpful for this case.
As it is always the case when you work with multiple threads, it can cause some headache. But I got around it and thought it might be helpful for some of you.
Here is how I solved the scenario:
First, declare a static BackgroundWorker so you need to set it up only once on the page you want to use it. In the Loaded or OnNavigatedTo event, we are instantiating our BackgroundWorker.
worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true;
worker.WorkerReportsProgress = true;
Now, let’s add two very important properties: WorkerSupportsCancellation and WorkerReportsProgress. Both need to be set to true, otherwise you will get one InvalidOperationException after the other when running the code.
In my case, I created a separate method to start the BackgroundWorker and hook up to all important events:
private void RunBackgroundWorker()
{
worker.RunWorkerCompleted += worker_RunBackgroundWorkerCompleted;
//delegating the DoWork event
worker.DoWork += ((s, args) =>
{
//generating a loop
for (int i = 0; i < 100; i++)
{
if (worker.CancellationPending == true)
{
//set cancel to true to finish the cancellation on the next run in the loop
args.Cancel = true;
}
else
{
//calculate your time: seconds * 1000 / 100
Thread.Sleep(50);
worker.ReportProgress(i);
}
}
});
//can be used to fill a progress bar/show percentage
worker.ProgressChanged += worker_ProgressChanged;
//start the BackgroundWorker
worker.RunWorkerAsync();
}
You might notice that I created a loop that runs up to 100. This is necessary for my solution, as this is the key to make the BackgroundWorker cancelable in my solution. Every 50 milliseconds, the CancellationPending property gets checked as I am looping through until the count reaches 100. I am setting an offset of 50 milliseconds, as I want to have a total offset of 5 seconds.
Next, let us set up a button that cancels the background task (can be used in other events/methods, too):
public void CancelButton_Click(object sender, RoutedEventArgs e)
{
//check this always to avoid InvalidOperationExceptions
if (worker.WorkerSupportsCancellation == true)
{
//request cancellation of the BackgroundWorker
//this sets the CancellationPending property to true
worker.CancelAsync();
}
}
Important: Always check if the Cancellation is supported by your BackgroundWorker to avoid those ugly InvalidOperationExceptions. Then, simply call the CancelAsync() method of your BackgroundWorker to set the CancellationPending property to true.
When the BackgroundWorker has completed (or cancelled), the value of the CancellationPending property is passed to the RunBackgroundWorkerCompletedEvent, where you can simply use the e.Cancelled property to continue your code (which will then be back on your main application thread):
private void worker_RunBackgroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
//your code in case the BackgroundWorker was cancelled
}
else
{
//your code in case the BackgroundWorker was running until the end
}
}
The last event I want to mention is the ProgressChanged event. It can be used to display a percentage or similar things, I just use it to see when the cancellation gets active:
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//your code here, for example display percentage or fill a progress bar
//use the line below to check the percentage and if CancellationPending property gets changed
//Debug.WriteLine(e.ProgressPercentage + " " + worker.CancellationPending);
}
With this few methods we can create a time based offset on a BackgroundWorker while keeping it cancelable at any time. The code above should work in similar form also on other platforms like Windows 8 or Xamarin.
As always, I hope this will be helpful for some of you.
On my daily job, I am working as a Mobile Hardware Support Agent of a German carrier. Because of that, I know how important a good support for customers (=users) is – and also, a little knowledge base where users can find most probably an answer for their questions.
I want my customers to be satisfied. As an indie developer, I have a little problem: I don’t have a support team that catches all the support questions for me. I need to do this by myself. Until now, I am doing this by using a send-me-a-mail button in my apps. However, due to the fact that I have a 9to5 job and a family besides developing apps, time is a bit limited for me. I searched for some solutions to improve the way I am doing my customer service, and uservoice seems like a good tool to improve my customer service a lot.
As you can see at the feature comparison list of uservoice, the free account already allows you to do a lot of things: https://www.uservoice.com/plans/?ref=top_pricing. It is free for one support agent – perfect for an indie developer like me.
What can you do with uservoice?
uservoice has a lot of features:
support ticket system
knowledge base
feedback system/forum
and many more, if you are going for a paid plan
Let’s have a look at the first three features:
Support ticket system
Adding the ticketing system is very easy. You just need a EMailComposeTask pointing to your ticket system. Your standard mail address for that will be: “tickets@<yourname>.uservoice.com”. This is how a received ticket looks like:
Answering to a user is as easy as writing an email – plus you have a ticket history at a glance.
On top of that, you are able to insert a so called ‘canned response’ based on your knowledge base:
Knowledge base
You can build up a knowledge base for your apps.
In the left menu at the bottom at your admin console, you will find the ‘ARTICLES’ section. This is where all the knowledge base articles are collected.
You can create also topics within that KB. I did so for all of my apps:
This way, you can use your free account to support all of your apps with FAQ/KB articles – pretty easy.
Here is how to set up a new article: after clicking on ‘All articles’, there is a ‘New Article’ button on the right side of your screen. Click on that, you will see this on the right hand side:
You can set up the article name, the text and the topic as well as the position you want to show it up in your knowledge base.
How can you use this in your apps? I plan to create an API wrapper for their C# SDK, which is not compatible with Windows Phone at the moment. I will write another blog post for that. Luckily, uservoice as a very nice mobile interface, so you can start off with a simple WebBrowserTask to open your knowledge base:
Technically, it would be possible to use a WebBrowser control, too. But you would need to code more to get a proper browsing handling.
Feedback system/forum
Some of you might be already familiar with the feedback or idea forum of uservoice (even Microsoft uses this). This time, we look at the other side of the forum, from our admin console:
You have a similar view to what users see, but there are some more parts to control your forum. As a free user, you have only one forum, so it might be useful if you add the app name in front of the title of an idea. You can respond, take notes, and change the status of the ideas:
To integrate the feedback function in your app, you can again use a WebBrowserTask to open the mobile page of your idea forum:
These are the first simple steps to create your own customer support system with uservoice. Like I said before, I will write a Windows Phone wrapper to get this into an app as native, and will share it here with you all.
2013 was a year with a lot of surprises. It was a year full of community work for me as well as a huge learning year in development. But my year had also dark clouds on heaven. This post is my personal review of 2013 – you can like my impressions or not.
I started the year with releasing my first Windows 8 app ever, along with an huge update to my blog reader app for Windows Phone. I wrote several blog posts and started also development of my NFC Toolkit app for Windows Phone (Archive: January). I also ran a beta test for my NFC Toolkit, and finished my series about the parts that should help other developers to write a blog reader app for both Windows and Windows Phone (Archive February & Archive March).
Then in April, the first time I had dark clouds hanging deeply in my life, affecting all parts – family, community work and also my 9to5 job. My wife had once again problems with her back, caused by slipped discs. It went as far as she needed to rest in hospital for a pain therapy. Luckily this therapy was helping her and our life went back to normality (knocking on wood).
I also started a new series on the WinPhanDev blog – Why we started developing (WWSDEV). We are collecting stories from developers, and posting them over there to motivate other developers and keep the community spirit alive. Just have a look, we have really great stories over there.
In the last days of April/beginning of May, Iljia engaged me to start using Windows Azure Mobile Services to make an app idea reality: TweeCoMinder was born. It is a very special and unique app, interesting for those that don’t want to miss their special counts on Twitter, supported by real push notifications via WAMS for both Live Tiles and Toast Notifications. I learned a lot during setting up my WAMS for the app, and I did also write some blog posts about that (AzureDev posts).
Because of TweeCoMinder, I stopped developing my NFC app for that time, and did only bug fixing updates to my other apps.
In August (at least in the spare time I had), I moved my blog completely to run in a Windows Azure VM. I did it to get more control over the whole system and to learn more about running a web service. I still need to write my blog posts about setting the VM with LAMP on Azure, but I just didn’t have time for that until now. In August/September I also had again very very dark clouds hanging around, with my wife was very ill (you can’t even imagine how happy I am about the fact she has this part behind her). But our daily live is still affected by this – we just learned to arrange us with the new situation.
In October, I got back to my NFC Toolkit to finish it finally. The app has some cool and unique features utilizing NFC tags, and I am quite satisfied with my download numbers. NFC Toolkit is my main project for the moment.
But also on my 9to5 job I came to write code. I was asked to write an internal app for Windows Phone (Telefónica has a partnership with Microsoft, and so the company is flooded with Windows Phones). I used this to learn more about speech recognition on Windows Phone, as this is part of the application (Make your app listening to the user’s voice).
And finally, I also started with my very first Android app using Xamarin while porting the Windows Phone app I wrote before. I recently started to blog about my experiences with Xamarin (read more here).
In between all those projects, I made a basic reader app for the fan blog “This is Nokia”, using a PCL project for both Windows Phone 8 and Windows 8. I also wrote a simple car dashboard app to integrate it in my NFC Toolkit app as well as Mix, Play & Share, which was written on a lonely Saturday night while my kids where sleeping an my wife was at her best friend.
Through the year, I learned a lot of coding, but also a lot about people. I made some very positive experiences – but also bad ones. I am always willing to help (if my still growing knowledge enables me to do so) – but sharing a feature rich app to another person isn’t helping – if you want to learn about development, there are plenty ways to do so. We have really great developers that blog about their experiences in our community, and by understanding how to code, you truly learn. Just using an already working app and restyling it, is the wrong way.
Well, that is what my year was about – a lot of coding, learning and again coding.
Dear followers, friends, WinPhans & WinPhanDevs – thank you for being with me this year. Let’s make 2014 an even more exciting year.
I wish you all “a good slide into the new year”, as we say here in Germany. May god bless you and your families also in the new year.
Microsoft introduced custom uri schemes or uri associations in Windows Phone 8 along with the ability to launch apps based on a file type.
Sadly, this feature is not used across a broad range of apps yet. Why am I so interested in that point? I am going to explain you.
First, there is one big issue: You can share any app via NFC, and launch any app from the Store via NFC tag that has a launch app record. But you cannot launch any apps from your app – just those that have implemented a custom uri scheme. On the other two big operating systems, sharing between apps is meanwhile a standard feature used by a lot of developers.
Most of the settings pages have one of those uri schemes, for example the Wi-Fi settings page can be launched with this simple line of code:
I don’t know if other developers just don’t know about this feature or if they don’t think it is necessary. I talked to a lot of users of my app NFC Toolkit for Windows Phone 8, and all asked me to add the possibility to launch a desired app at the end of my profiles (if you don’t know, my profiles launch programmable sequence of settings pages).
Searching for a solution to satisfy my user, I spent a few days with researching of all possibilities and talking to other developers. Some of them wanted use cases for adding that feature, here are three:
Every day I leave for work, I disable Wi-Fi, activate Bluetooth and switch the cellular connection from 2G to 3G/4G. I often use Nokia Music to listen to music while driving to work (about 45 minutes). This is one of the use cases.
The second scenario should be also familiar to some of you: I switch off all data connections because otherwise, my phone would ring very often during the night. In the morning, I switch them back on and check for news with a feed reader app. This would fit perfectly into a profile that I save on a NFC tag or launch via secondary tile.
Third one: there are a lot of blog reader apps out there. Sure, Windows Phone has social networks built in – but only Facebook (user only), Twitter and LinkedIn. What if I want to share to another network, for example Geeklist? Then I have to copy and paste instead of just hitting the share button.
There are more use cases, but I am leaving you with these three for the moment.
Back to the conversations I had with my users. They want and deserve a great user experience. This blog post is part of my efforts to provide users their deserved user experience.
Sadly, for a handful of developers it is not as easy to gain some attention for this. This is why I am trying to get DVLUP on board. By creating a challenge for this, more developers would join to earn the XP. The winners in this case are the users out there, because this way, their user experience will be improved. I know this should be done by Microsoft. In the meantime, it is up to us developers to improve. That’s why I ask you to vote for my idea case on DVLUP here: http://www.dvlup.com/Feedback?query=custom+uri+scheme+to+all+apps%21# (the first entry in the list is the one to vote).
There is one reason left why you should add a custom uri scheme to your app. This point is for you, the developer reading this article. You have a free possibility to promote your app across other apps. The most important point: it takes only 5 minutes to add a simple launch uri scheme.
Do you already have a custom uri scheme for your app? Great, then add it to this list: URI Association Schemes List – Nokia Developer Wiki. This way, other developers can use them to interact with your app and bring you new users, too.
To close this article, I want to show you how to add a simple custom uri launch scheme. I have done this with my app Mix Play & Share recently (update submitted, will add it to the list above as soon as it certified).
A simple launch uri – the code
First, open your WMAppManifest.xml by right-clicking on it and Open with… =>XML (Text) Editor.
After the </Tokens> Element, add the following code:
I hope after reading this post, you understand why I think it is important to add a custom uri scheme. With the simple code above, you’re done in 5 minutes.
Update 12/14/2013:
I needed to update the UriMapper class above, because without handling a scheme without parameters we will have no guarantee that the app launches. In my tests it works sometimes and sometimes not, but to make sure your app launches, please handle this case properly.
In one of my recent projects, I needed to update the live tile of the app via a background agent with data from a WordPress based web site. I did what I always do when implementing a feature I never used before: researching.
I found tons of example on how to update the live tile periodically, but non of them told me how I can use the data from the web site or where I need to put it in.
In the end, it was Jay Bennet, developer of the fantatsic WPcentral Windows Phone app, who gave me the last hint I needed – where do I start the request for the data I need. Thanks to him for that!
Ok, but let’s start in the beginning. When it comes to web based services, you first need a class (or ViewModel) that can hold your data you receive from your service. I explained that already pretty well here. No matter if you are running your request within your app project or in a PCL, it pretty much always works like this.
After stripping of our class out of the JSON string, we are now able to create our request as well as our Background Agent.
The first thing you need to do is to add a Windows Phone Scheduled Task Agent. Create a new project within your app and choose the project type mentioned before. Then, in your main project, add it as a reference (right click on References/Add Reference/Solution => select your background agent project there. That’s it.
No go to your ‘ScheduledAgent.cs’ file and open it. You will find this code in there:
protected override void OnInvoke(ScheduledTask task)
{
//TODO: Add code to perform your task in background
NotifyComplete();
}
And thanks to Jay, I know that this is where all the action (not only updating the tile like in all samples I found) happens. This may sound very trivial for those of you who have experience with that, but if you’re new to it, it may hold you back a bit. However, there are a few points you’ll need to take care of:
you only have 25 seconds to perform all action here
your task will run every 30 minutes, no way to change that
scheduled tasks need to be restarted within 14 days after the current start
Battery saver and the OS/the user can deactivate the agent
there is a long list of what you are not able to do in here (check MSDN)
all action needs to be finished before NotifyComplete() is called
Based on this information, I created my task as following:
protected async override void OnInvoke(ScheduledTask task)
{
//performing an async request to get the JSON data string
PostsFetcher postfetcher = new PostsFetcher();
Constants.latestPostsForLiveTileFromWordPressDotComResultString = await postfetcher.GetLatestPostFromWordPressDotComForLiveTileOnPhone();
//deserialize all data
var lifetileBaseData = JsonConvert.DeserializeObject<json_data_class_Posts.Posts>(Constants.latestPostsForLiveTileFromWordPressDotComResultString);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
//using Telerik's LiveTileHelper here
Uri launchUri = new Uri("Mainpage.xaml", UriKind.Relative);
RadFlipTileData fliptileData = new RadFlipTileData();
fliptileData.BackContent = lifetileBaseData.posts[0].title;
fliptileData.WideBackContent = lifetileBaseData.posts[0].title;
fliptileData.BackTitle = string.Format("{0} {1}", DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString());
fliptileData.Title = "LiveTileTitle";
if (lifetileBaseData.posts[0].featured_image != string.Empty)
{
fliptileData.BackgroundImage = new Uri(lifetileBaseData.posts[0].featured_image, UriKind.RelativeOrAbsolute);
fliptileData.WideBackgroundImage = new Uri(lifetileBaseData.posts[0].featured_image, UriKind.RelativeOrAbsolute);
fliptileData.BackBackgroundImage = new Uri("Images/BackBackground.png", UriKind.RelativeOrAbsolute);
fliptileData.WideBackBackgroundImage = new Uri("Images/WideBackBackground.png", UriKind.RelativeOrAbsolute);
}
else
{
fliptileData.BackgroundImage = new Uri("Images/PlaceholderBackgroundImage.png", UriKind.RelativeOrAbsolute);
fliptileData.WideBackgroundImage = new Uri("Images/PlaceholderWideBackgroundImage.png", UriKind.RelativeOrAbsolute);
fliptileData.BackBackgroundImage = new Uri("Images/BackBackground.png", UriKind.RelativeOrAbsolute);
fliptileData.WideBackBackgroundImage = new Uri("Images/WideBackBackground.png", UriKind.RelativeOrAbsolute);
}
foreach (ShellTile tile in ShellTile.ActiveTiles)
{
LiveTileHelper.UpdateTile(tile, fliptileData);
}
});
NotifyComplete();
}
As I fetch different data from the site, I create a class that holds all request methods. In those methods, I just created an HttpClient that downloads the desired Json string into my app. I take only the first post in the case above, to make the live tile updating also on slow internet connections within the 25 seconds and to not reach any memory limit. In the end, I use Telerik’s LiveTileHelper to create a FlipTile with image and text from the site (the image will be downloaded automatically).
That’s all we need to to in the Scheduled Task Agent. Now we need to implement the agent into our app project.
First thing we should implement is a switch where the user can turn our agent on and off. I used a ToggleSwitch for that, saving the isChecked state as a Boolean to the IsolatedStorage of my app.
Knowing I need to restart the background agent after some time, I implemented the agent handling in App.xaml.cs. This way, I need to write less code as I tend to use separate settings pages. The only thing you need to think of is to set up all objects as static and public.
First, we need to declare a PeriodicTask as well as a name for it:
public static PeriodicTask LiveTileUpdaterPeriodicTask;
public static string LiveTileUpdaterPeriodicTaskNameString = "LiveTileUpdaterPeriodicTaskAgent";
Now we need to generate a method that handles everything for our background task:
public static void StartLiveTileUpdaterPeriodicTaskAgent()
{
//declare the task and find the already running agent
LiveTileUpdaterPeriodicTask = ScheduledActionService.Find(LiveTileUpdaterPeriodicTaskNameString) as PeriodicTask;
if (LiveTileUpdaterPeriodicTask != null)
{
//separate method, because we need to stop the agent when the user switches the Toggle to 'Off'
StopLiveTileUpdaterPeriodicTaskAgent();
//contains:
//try
//{
// ScheduledActionService.Remove(App.LiveTileUpdaterPeriodicTaskNameString);
//}
//catch { }
}
//generate a new background task
LiveTileUpdaterPeriodicTask = new PeriodicTask(LiveTileUpdaterPeriodicTaskNameString);
//provide a description. if not, your agent and your app may crash without even noticing you while debugging
LiveTileUpdaterPeriodicTask.Description = "This background agent checks every 30 minutes if there is a new blog post.";
//start the agent and error handling
try
{
ScheduledActionService.Add(LiveTileUpdaterPeriodicTask);
}
catch (InvalidOperationException exception)
{
//user deactivated or blocked the agent in phone settings/background tasks. Ask him to re-activate or unblock it
if (exception.Message.Contains("BNS Error: The action is disabled"))
{
RadMessageBox.ShowAsync("it seems you deactivated our Background Agent for the Live Tiles. Please go to settings/background tasks to activate our app again.", "Whoops!", MessageBoxButtons.OK);
}
//the maximum of running background agents is reached. No further notification to the user required, as this is handled by the OS
if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added."))
{
//changing the Boolean to false, because the OS does not allow any new taks
isLiveTileActivated = false;
}
}
catch (SchedulerServiceException)
{
//if there is a problem with the service, changing the Boolean to false.
//feel free to inform the user about the exception and provide additional info
isLiveTileActivated = false;
}
}
In Application.Launching() and in ToggleSwitch_Checked event, call this method. In ToggleSwitch_UnChecked event, call ‘StopLiveTileUpdaterPeriodicTaskAgent()’ instead to stop the agent.
Before we are now able to debug our agent, there are two things left. The first thing is to declare
#define DEBUG_AGENT
in the very first line of ‘App.xaml.cs’ as well as in ‘ScheduledAgent.cs’ before all using statements.
The second thing is adding an if-Debug command to our ‘StartLiveTileUpdaterPeriodicTaskAgent()’ and also to our ‘OnInvoke(ScheduledTask task)’ methods:
Add this after adding the task to the SchedulerService in our agent starter and before ‘NotifyComplete()’ in ‘ScheduledAgent.cs’.
If you run the project now in Debug mode, your agent will be debugged and forced to run after 60 seconds. If you run the project in Release mode, Visual Studio will throw an ‘Access Denied’ error, so make sure you set it up correctly.
If you follow all steps above, you will be able to add a Live Tile updated via background agent very easily to your app.
As always, I hope this real world scenario will help some of you.
I am currently exploring a lot of APIs that I never used before in my Windows Phone apps as I am adding more features to my NFC Toolkit.
Like I always do, I create sample applications to explore what is possible and then integrate them into my main app.
One of those APIs is the MediaLibrary class on Windows Phone. You might think: there are tons of examples out there, why another post? Well, I agree, there are a lot of samples, but I want to cover a whole scenario.
In my sample, I am getting a list of all Albums stored in Library, start them playing, and display the current playing song as well as handle state managements of the playing song.
First, you will need to add the capabilities ID_CAP_MEDIALIB_AUDIO and ID_CAP_MEDIALIB_PLAYBACK to your app. If you will not do that, every call against the APIs will end up with an NotAuthorizedException.
For any access to the MediaLibrary and the MediaPlayer classes we are using the Namespace “Microsoft.Xna.Framework.Media”. Here our trouble begins already.
Xna is Microsoft’s framework to create games on Windows Phone 7. As Windows Phone 8 supports also native code, this is mainly used in 7 games. That’s why you might run in some TargetInvocationExceptions while you debug apps that use them.
To avoid this, we need to add a Framework Dispatcher that simulates a game loop for us. Add the following method to your App.xaml.cs:
We are starting a new GameTimer and delgate it to our UI using the FrameworkDispatcher.Update() method. By adding it to App.xaml.cs and calling this method in Lauching and Activated event of our app, we have it running through our whole app and are done with this.
There are several methods to this, I found this the most easy version. I would pay credits, but don’t remember where I saw this – sorry.
Before we came to our first call against the MediaLibrary, we need to add a class for our List<T> or ObservableCollection<T>. I don’t know if this is the best practice in this case, but it made working with the List of Albums very easy for me:
public class AlbumFromStorage
{
public string AlbumName {get; set;}
public string AlbumArtist {get; set;}
public WriteableBitmap AlbumCover {get; set;}
public SongCollection AlbumSongs { get; set; }
}
To use this class, just add a new List<T>/ObservableCollection<T> to the Page class. Do the same for a MediaLibrary object and an AlbumCollection object:
public ObservableCollection<AlbumFromStorage> AlbumsList = new ObservableCollection<AlbumFromStorage>();
public MediaLibrary lib = new MediaLibrary();
public AlbumCollection albumslist;
Now we are prepared for fetching all local stored albums. Add the following code to your corresponding method:
albumslist = lib.Albums;
if (albumslist.Count != 0)
{
foreach (var item in albumslist)
{
AlbumsList.Add(new AlbumFromStorage()
{
AlbumArtist = item.Artist.ToString(),
AlbumName = item.Name,
AlbumCover = PictureDecoder.DecodeJpeg(item.GetThumbnail()),
AlbumSongs = item.Songs
});
}
MusicAlbumListBox.ItemsSource = AlbumsList;
}
else
{
await MessageBox.Show("It seems you have not stored any music on your phone.", "Sorry :(", MessageBoxButton.OK);
}
Let me explain the code. First, we are using our AlbumCollection object to asign the MediaLibrary.Albums property. This will give us a collection of all albums. Then we need to check first, if the count in the collection is not 0 (it will throw ugly exceptions if a user doesn’t have any music stored if you won’t to this).
Then we add these albums to our ObservableCollection<AlbumFromStorage> picking the interesting properties of each album for us.
As the thumbnail for the album cover is a Stream, we need to use a WriteableBitmap for calling the GetThumbnail() method. The last step adds our ObservableCollection<AlbumFromStorage> as ItemSource to our ListBox.
This will be the result (based on my current albums list):
Now all we need to do is to make a tapped album playing with Windows Phone’s media Player. Add the following code to the Listbox ItemTap Event:
if (Microsoft.Xna.Framework.Media.MediaPlayer.State != MediaState.Playing)
{
//to delete the recent song (if there is any), just add this
MediaPlayer.Stop();
var selectedItem = this.MusicAlbumListBox.SelectedItem as AlbumFromStorage;
// play the SongCollection of the selected Album
MediaPlayer.Play(selectedItem.AlbumSongs);
}
else if (Microsoft.Xna.Framework.Media.MediaPlayer.State == MediaState.Playing)
{
MessageBox.Show("You are already playing music. Please stop the music first.");
//your own handling could be different here, like asking the user for the desired action and perform it then
}
As you can see, I use the MediaPlayer.State property to get the album playing. The album is a SongCollection that holds all songs of the album. I recommend you to stop the last played song (if there is any) first with the MediaPlayer.Stop() method before start playing the first album song with the MediaPlayer.Play() method. Otherwise, it may happen that the user hears a second from the old song.
Very important: you must handle the case that the user has already music playing. If not, your app is likely to not pass certification.
After we started playing the music, we naturally want to display the current song.
This way, we use the MediaState to display the the current state as well as the title and artist. As we are updating the UI thread, as Dispatcher is used to update the Text.
To change the title and the artist of the current playing song, use this code within the MediaPlayer_ActiveSongChanged event:
If you want to display also the album image, you will need to cache the image from the ItemTap event before, which would work fine with albums. If you choose Playlists instead of Albums, this will not work out well as you will not be able to get the image from MediaPlayer.Queue.ActiveSong.
I did a lot of research to get this feature(s) working the way they should. I took me several hours to figure everything out exactly, and I hope this post helps some of you out there to save some time on this.
With this post, you will be able to generate the whole experience your users deserve from the beginning to the end.