This is the last post in my 4 part series. The previous posts in this series covered the basics for creating a simple Xamarin.Android Video Player application. Feel free to check them out to see how we built a basic Video Player:
Part 1 – Using VideoView
Part 2 – Adding Media Controls
Part 3 – Progress Indicator and Orientation Changes
In this final post, we will polish off our Video Player by taking steps to ensure the application does not fail in the event a network connection isn’t present, since we are loading videos from an external site. We will listen for changes in the network connection while the application is running so that when the connectivity state changes we can handle it accordingly. We will display a relevant error message when no connection is found, and we will attempt to resume the video playback when the connection is restored.
Let’s take a look at the classes provided through the API which enables us to monitor the current network connection on a device.
ConnectivityManager and BroadcastReceiver
The ConnectivityManager is a class which provides information on the current network connection (i.e. whether there is a connection and the type of connection), monitors for network connectivity changes, and broadcasts a connectivity action when any connection details have changed.
The BroadcastReceiver is a base class that will receive notifications in the form of intents when another application or the system triggers the SendBroadcast(Intent) method. An intent will contain an action string and optional data that will be received by any applications that are registered as receivers.
To enable your application to listen for connectivity change notifications broadcast by the ConnectivityManager, you must register a broadcast receiver by adding the following line to your AndroidManifest.xml file:
In addition to that, because you are accessing information about network state, you will need to include the necessary permission in your AndroidManifest as well:
Next, you must extend the BroadcastReceiver base class and override its OnReceive(Context, Intent) method. Within this override method, you can check the intent’s Action to determine if and how you will respond to the broadcast intent within your own application.
The Connectivity Plugin
Now that you have an understanding of the basic components that help you to monitor network connections in an Android application, I have some good news – Xamarin’s own James Montemagno has already written a plugin for that and made it available as a Nuget package :)
The Connectivity Plugin contains the necessary code for retrieving information about the network, monitoring for network connections and listening for connection changes.
The best part of this plugin is that it is a complete cross platform solution, so that you can use it in your client applications and Portable Class Libraries. He has provided both the abstraction layer and the necessary platform-specific implementations (ie. Android, iOS, Windows 8.1 and Windows Phone (8.0 & 8.1)). The Connectivity Plugin handles loading the platform-specific implementation logic. All you have to do is make the appropriate calls through the plugin’s IConnectivity interface which is exposed through the CrossConnectivity.Current static property. At runtime, the Connectivity Plugin will load the platform-specific implementation and make it available through CrossConnectivity.Current.
This may not seem like a big deal now, since we are only targeting Android. But if you ever wanted to expand your application to target multiple platforms, you will realize a huge time savings from only having to call one API rather than code each platform’s implementation to achieve the desired result.
James has made the entire solution for the Connectivity Plugin available on his Github account. Feel free to peruse the code or download it and customize it for your needs.
Side Note: When using 3rd party components, be sure to provide proper attribution within your application - for example, by adding a Credits page that lists the components you used, along with their respective authors. These components are provided by developers to make your life easier, so it’s important to give credit where credit is due.
Using the Connectivity Plugin in our Android Project
To add the Connectivity Plugin to our application, right-click on the project in Solution Explorer, and select Manage Nuget Packages. Within the Manage Nuget Packages dialog, search for Xamarin Connectivity. Install the Connectivity Plugin for Xamarin and Windows.
Once the Connectivity Plugin has been added to the project, take a look at the project’s references. Notice that it added two new references to the project – Connectivity.Plugin and Connectivity.Plugin.Abstractions.
In the MainActivity code file, add using directives for these namespaces:
There are two things we care about and need to account for:
1) listening for changes in network connectivity
2) performing the appropriate check so the video attempts to load only when a network connection is present
To monitor for changes in network connectivity, we need to register an event handler for the ConnectivityChanged event. Add the following to the OnStart method:
CrossConnectivity.Current.ConnectivityChanged += OnCurrentConnectivityChanged;
Be sure to unregister the event handler in the OnStop method as well.
Next, we need to include the action we want taken when the network connectivity changes. In this scenario, we only care about whether or not the video can play. Since the LaunchVideo method is responsible for starting the video playback, let’s include a check to only start the playback if the network is currently connected, so that no matter where it’s called from, we are performing our due diligence. I am also going to ensure that the video player isn’t in the middle of playing the video already since LaunchVideo is called from multiple locations.
Then in our OnCurrentConnectivityChanged event, we can simply call the LaunchVideo method as is, since it’s already checking to ensure an active connection before playing the video. Alternatively, you could check the state of the connection within this event handler through the ConnectivityChangedEventArgs.IsConnected property. It’s up to you, whichever way you prefer to handle it.
Now, we want to be able to display a status message when the network connection is lost. Let’s add a TextView to the MainActivity layout.
Notice that the text of the control is set to a custom string definition. Add the following to your Strings.xml file:
With the TextView in place, we now need to ensure we set the view states on the VideoView, the ProgressBar and our new TextView based on connection state. When there is no network connection, we want only the status message (ie. the TextView) to display, otherwise it is hidden and the ProgressBar and VideoView will display.
Let’s create a separate method called UpdateVideoPlayerState, and include the code to achieve this:
However, we also need to account for hiding the TextView, and displaying the VideoView and the ProgressBar when the network is connected. We also want to be able to call this method anytime we need to update the state of the controls in the video player, so let’s extend it to also be able to hide the ProgressBar in the event the video is ready to play. We can do this by passing in a boolean parameter to indicate the state the video player is in when connected, as follows:
Again, note that we are also checking to make sure the video player isn’t in the midst of playing the video, since this method is also called from multiple locations.
Tip: If you’re wondering why we do not set the VideoView’s Visibility to Gone or Invisible when the ProgressBar is displayed, it is because the VideoView will not fire events when hidden. Since we registered an event handler for its Prepared event in order to determine when to trigger the video playback, we need to ensure it remains Visible in this scenario.
Now we can simply add the call to UpdateVideoPlayerState, passing in a false value when the video player activity first starts, when the configuration changes or connectivity changes.
When the OnVideoPlayerPrepared event is triggered, we know the video is ready to play, so let’s call updateVideoPlayerState passing in a true value, as follows:
Last but not least, don’t forget to modify the AndroidManifest.xml to register a broadcast receiver and to request permission to access network state as we discussed earlier.
Playing Video only when connected to WiFi
If you only want the application to play the video when connected to a WiFi network, you can easily modify the existing code to check to see if the device is currently connected to WiFi. The Connectivity Plugin exposes a collection of all the current active connection types. So we can include a bool property which returns true or false if the device has a WiFi connection:
Note that we are using a simple LINQ query to check for a WiFi connection type. This requires the inclusion of the following using directive within your class:
Replace the checks from CrossConnectivity.Current.IsConnected to IsConnectedToWiFi.
At this point, you can run and test the application. Play around with turning on/off WiFi connections while the video is loading and while the video is playing to see what happens. I know you will find more ways to improve upon this sample application just by testing it out. I hope this gives you a good starting point to work from. You can check out the completed project on my Github account..
In Part 1 of this series, we developed a simple video player using Android’s VideoView. However, in testing the application, it is obvious that there are some key features missing. Let’s take a look at how we can improve our Video Player application to provide a better user experience.
Where are the media controls?
The first noticeable thing that seems to be missing from our Video Player is the play, rewind, and fast forward buttons, as well as the progress slider that we are used to seeing when watching videos in other popular video players. The user will not be able to control video playback without it, which isn’t ideal. Luckily for us, it is very easy to incorporate this within our Xamarin.Android application.
The Android API provides a MediaController view, which contains the play/pause, skip forward, and skip back buttons along with a progress slider. To make use of the MediaController, we will need to instantiate it programmatically, and associate it with the VideoView, as follows:
private MediaController mediaController;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
videoPlayer = FindViewById<VideoView>(Resource.Id.PlayerVideoView);
mediaController = new MediaController(this, true);
videoPlayer.SetMediaController(mediaController);
}
The constructor we are using for the MediaController requires that we pass in the current context, which is the current Activity, and a boolean value to indicate whether or not to show the rewind and fast forward buttons. With the code above in place, the MediaController will display the Play/Pause button, the rewind and fast forward buttons, and the progress slider. If you wish to hide the fast forward and rewind buttons, simply pass in false as the second parameter value instead.
To ensure that any action the user takes on the MediaController affects the video playback accordingly, we must associate the MediaController with the VideoView by calling the VideoView’s SetMediaController method and passing in a reference to the MediaController. Not only does this allow the user to control the video playback with the controller, but it also registers a touch listener that is associated with the VideoView so that when the view is tapped, the MediaController will appear. There is nothing else we need to do at this point. We can run the application and the MediaController will just work. We can play, pause, fast forward and rewind the video without any additional coding needed on our end. When the MediaController disappears from the view, tap the video to make it reappear.
Test out the application so far, play with the media controls and switch the device orientation from portrait to landscape mode while the video is playing. Notice that when the video playback starts, we don’t see the MediaController on the screen at all. In order to display the controls, the user must touch the video to force it appear. This isn’t really intuitive. It would be ideal to show the user that the MediaController is there when the video starts to play, and then hide it after a brief period, let’s say 3 seconds.
The MediaController provides a Show method, which accepts a timeout in milliseconds for this purpose. It will force the MediaController to appear and remain visible for the specified time.
Since we want the controller to appear when the video playback starts, we will handle this in the VideoView’s Prepared event, which is triggered when the video is ready to play. Register this event in the Activity’s OnStart method:
protected override void OnStart()
base.OnStart();
videoPlayer.Prepared += OnVideoPlayerPrepared;
LaunchVideo();
In the same respect, we should unregister the event in the OnStop method:
protected override void OnStop()
base.OnStop();
videoPlayer.Prepared -= OnVideoPlayerPrepared;
Next, we will add our custom OnVideoPlayerPrepared event handler and call the MediaController’s Show method, as follows:
private void OnVideoPlayerPrepared(object sender, EventArgs e)
//show media controls for 3 seconds when video starts to play
mediaController.Show(3000);
Run the application in portrait mode. Notice that the media controls are displayed at the bottom of the screen, far removed from the video.
Would it be preferable to render the controller as an overlay on the video? We can easily make that change by calling the MediaController’s SetAnchorView method and passing in a reference to the VideoView. This will enable the MediaController to know where to position itself when it is rendered onscreen. The media controls will then be displayed as an overlay at the bottom of the anchored view.
To achieve this effect, add a call to the SetAnchorView method in the OnVideoPlayerPrepared event:
mediaController.SetAnchorView(videoPlayer);
mediaController.Show(MediaControllerTimeout);
Tip: If you attempt to call SetAnchorView from the OnCreate or OnStart methods, it will still render at the bottom of the screen. This is because the height of the VideoView is not known at this time. It’s best to call this method within the VideoView’s Prepared event when the video is loaded and its size is known, to ensure the controller is properly anchored to the VideoView.
Run the application again ensuring the device is upright (in portrait mode).
Notice that the MediaController appears as an overlay on the VideoView, aligned with the bottom of video. This is much nicer than having the controller floating at the bottom of the screen away from the video itself.
Wrapping Up
In this post, we built upon our basic Video Player application by associating a MediaController to the VideoView, enabling users to control video playback (i.e. pause, resume, skip forward and rewind). We also covered how to anchor the controller to the VideoView and force the controller to appear for a few seconds when the video first loads. In Part 3 of this series, we will look at providing some polish to the VideoPlayer by handling video playback when the orientation changes, and displaying a progress indicator while the video is loading.
Recently, I was tasked with including video playback within a Xamarin.Android application, so I decided to write a blog post series about my approach in hopes it helps others who are building similar apps.
Incorporating videos within your Xamarin.Android application can be handled in a couple of ways. You can load and play the video in the application or you can launch the video in an external installed media player on the device. In this post, we will walk through the steps to incorporate videos right within the application using Android’s VideoView. We will develop a simple demo that loads a video from a URL.
Modifying the Android Manifest
Since we will load a video from a URL, we must add the following permission to the AndroidManifest.xml file:
<uses-permission android:
Adding the VideoView to an Activity
In order to play a video within a Xamarin.Android application, we will use a VideoView which can load and play videos from a specified path or URI.
For this post, let’s create a simple demo to illustrate the main concepts of creating a basic video player to display videos and whose orientation will change when the device is rotated. In this case, we will just use the MainActivity to display the video full screen.
Modify the MainActivity.axml file to include a VideoView within a RelativeLayout, and configure the VideoView to appear center screen as follows:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android=""
android:layout_width="match_parent"
android:
<VideoView android:id="@+id/PlayerVideoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:
</RelativeLayout>
Within MainActivity.cs, we need to obtain a handle to the VideoView in order to specify the URI of the video to play, and then trigger the video to launch when the activity is loaded:
[Activity(Label = "VideoPlayerDemo.Droid",
MainLauncher = true,
Icon = "@drawable/icon")]
public class MainActivity : Activity
private VideoView videoPlayer;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
videoPlayer = FindViewById<VideoView>(Resource.Id.PlayerVideoView);
}
protected override void OnStart()
base.OnStart();
LaunchVideo();
private void LaunchVideo()
//do the guys in this video look familiar?
string videoUri = "";
videoPlayer.SetVideoURI(Android.Net.Uri.Parse(videoUri));
videoPlayer.Start();
At this point, the video will play and will rotate when the device is rotated, which is great! With very little effort, we were able to easily incorporate video playback within the application, but there are some additional features we can include to enhance the user experience. In Part 2 of this series, we will look at improving upon our simple video player by adding media controls and incorporating a progress indicator while the video loads.
The Spotlight posts are back again! For this post, I decided to interview Andy Houghton, an IT professional and a member of Canada’s Technology Triangle .NET User Group, who regularly attends the sessions and full day workshops.
Andy understands that an important aspect in the IT field is continuous learning. He is a super star on the Microsoft Virtual Academy track, achieving Platinum status with over 14K points. Andy is currently ranked among the Top 10 overall MVA students in Canada.
If you haven’t heard of Microsoft Virtual Academy, then check out my short post, Microsoft Virtual Academy – Free Training At Your Fingertips
Background
Andy Houghton has been in the IT community since 1988. He has held many IT roles from Help Desk to Programmer to IT Manager. Andy enjoys working, and helping others grow, in technology. He is currently working on a contract at the Co-operators Insurance Company in Guelph, Ontario. Outside of work, Andy and his wife provide a safe place for children as foster parents. He also has a 19 year old daughter who recently completed her first year of university.
I had a chance to ask Andy some questions about how he got started with MVA, and how it has impacted his career.
1) When did you first get started with Microsoft Virtual Academy (MVA)?
I started using MVA on June 24th, 2011, which was the second week it was available.
2) How did you hear about it?
I received an email from Microsoft.
3) How many courses have you completed through MVA to date?
To date, I have completed about 120 courses.
4) What is your motivation for pursuing the MVA courses?
Keeping current on new technology.
5) How has your career changed since taking the MVA courses?
I have been able to improve my skills and get more contracts. I also feel more confident that what I am telling customers is correct because I heard it on MVA. Sometimes in the past, you created your own solution and it was not the best practice. When I learn something on MVA I know it is the best practice, because it is coming from Microsoft.
6) Of all the courses you’ve taken, what is your favourite MVA course? And who is your favourite MVA instructor?
The OneNote training was my favourite because it is what I use to keep track of my IT resources.
I do not have a favourite instructor I find all of them really knowledgeable and easy to listen to.
7) Are there any additional resources you use to continue to learn and grow in your field of expertise?
Besides MVA, I also use MSDN and TechNet websites. There is an abundance of user created content online which is really useful. Office 365 also has some separate resources that you can search for online.
I use OneNote notebooks to keep track of the best resources. I also make note of those resources that are not so good, so I know to avoid them in the future.
8) What advice can you give to new grads that are entering the workforce?
Never stop learning. I received one piece of advice from an MVA course that I will always remember. I am not sure what course it was, I believe it was an Office 365 course where the instructor said. If you want to continue to advance your career and make more money, “Be more valuable to your employer this year then you were last year”.
Wrap Up
The key to success in this field is the ability to change, and adapt, as new technologies emerge. Microsoft Virtual Academy is one of the many resources available online that help you to hone your skills, and keep current, at no cost to you. Thanks Andy for participating in this month’s Spotlight post!
Last but not least…
If you enjoy keeping up with the technology trends, I highly recommend that you register for Microsoft Virtual Academy and create your own personal learning plan. While you’re at it be sure to check out the upcoming Windows 10 Developer Readiness Canadian Webcast.
Online resources are awesome, but in-person events are just as important, both for the learning and the networking opportunities. If you’re in the GTA or surrounding area, register for the Toronto stop of the Build Tour as well as for the Build Highlights sessions that both I and fellow Microsoft MVP, Tom Walker, will be running for our local area .NET User Groups: London Developers .NET Meetup Group and Canada’s Technology Triangle .NET User Group (Kitchener).
I look forward to seeing you there!
Join the Windows 10 Developer Readiness – Powered by MVPs global webcast series to learn how to build an app or bring an existing App to the *NEW* Universal Windows Platform!
This live:
Canadian Webcast Details
Registration Link:®Now=1
Speaker: Colin Melia
Moderator: Tom Walker
Date: Thursday, June 11th
Time: 12pm EST
For more information, visit the event page:
It’s that time of year again! ObjectSharp’s At the Movies event is right around the corner, and we can’t wait to share all of the good things coming up in our industry this year! I really enjoy being a part of this event, and not just for the posters (but on an important side note, thanks to Denis Makarenko for his hard work in making those posters look amazing!). What’s important is the information we are bringing to you, so that you can get up to speed with the changes coming your way, and to show you how Microsoft is making it easier than ever to manage projects with TFS, integrate advanced services into your enterprise or mobile applications through Azure, and develop high quality applications for the enterprise or consumer market.
In a few short days, my fellow ObjectSharp colleagues and I will take to the stage at the TIFF Bell Lightbox in downtown Toronto to share all of the exciting advancements that Microsoft announced recently at its annual Build conference.
Shane Castle will talk about the sophisticated service offerings available in Azure which can easily be incorporated into your applications regardless of the platform they are running under.
Dave Lloyd and Max Yermakhanov will then step up to discuss the new features coming in TFS 2015 enabling you to easily set up your team and projects for success.
Last but not least, David Totzke and I will take to the stage to share with you what we learned firsthand while attending the Build conference.
Be sure to register for this event at! It’s free, it’s fun, and it’s full of information that is relevant to you! We are all looking forward to seeing you there!! app that allows you to track your favourite musician or band.
In Part 2, I demonstrated how you can get the majority of the app completed simply using Windows AppStudio. To complete the app, I mentioned that it would be necessary to download and modify the source code.
Before digging into the code, my last post was focused on looking at the solution and source code that was generated by AppStudio to gain a better understanding of the structure of the projects. This helps us to identify where modifications will need to be made.
The Necessary Changes
In order to ensure the Bandsintown concert listings are rendered in the application, and to allow users to link to the band’s concert page to purchase tickets, we need to make some changes. My goal for these changes are to show a concerts list with the name of the venue, the city and/or country the concert is in, and the concert’s date and time. I would also like to make it easy to see which concerts still have tickets available for sale.
Last but not least, when a concert item that has tickets available is tapped, I want to the app to load the concert’s ticket sales page.
To accomplish this, changes are required to the application logic within the Portable Class Library and Shared Project. Further changes are needed to each platform-specific project to ensure the user interface displays the data in a desirable format.
In the Portable Class Library:
1) Add a class, named ConcertSchema, to represent the data retrieved from the Bandsintown API.
You can easily add the members to this class from a JSON sample of the data in Visual Studio 2013. First, go to the Event JSON Response page on the Bandsintown API site:
Next, highlight and copy the sample Event data. Now go back to your ConcertSchema class in the Portable Class Library and delete the default class that is created. Click Edit > Paste Special… > Paste JSON As Classes
You will notice the main Events result set is created as a class called Rootobject. Any subsequent classes that are needed are automatically created as well (in this case, Artist and Venue).
2) Add a class, named ConcertDataProvider, to perform the web request which will retrieve the data from the Bandsintown API for your favourite artist. It also will translate the retrieved data into an object which we can use within the code. This is referred to as deserialization.
3) Rename the Rootobject class to ConcertSchema. For conformity, I also renamed the Venue and Artist classes that were generated to VenueSchema and ArtistSchema respectively. I also changed the data type of on_sale_datetime from DateTime to object, since this field may not always have a value, causing null exceptions to be thrown.
Try building the solution now to see if we are on the right track.
What happened? Did you notice an error similar to this:
The solution to this is to ensure the class derives from the BindableSchemaBase abstract class, similar to the way that the RssSchema class does:
public class ConcertSchema : BindableSchemaBase
Right-click on BindableSchemaBase within the ConcertSchema class, and select to implement abstract class:
Modify the override methods that were added as part of the abstract class implementation as shown below:
Since the concert listings pulls a DefaultTitle, DefaultSummary and DefaultContent for each list item, it’s easy to feed the concert data that we want to the concert item by just returning that information through these classes. AppStudio has already provided the bindings (or virtual glue) that wires everything together to get the data flowing from back to front.
4) Modify the ConcertsDataSource class to make use of the new Concert data provider.
In the Shared Project:
1) Modify the ConcertsViewModel in the Shared Project to utilize the new ConcertSchema class. This can be simply accomplished by replacing RssSchema with ConcertSchema.
2) Add an image to the Assets folder which will be used to represent a ticket. In this case, I used Syncfusion’s Metro Studio to obtain an image which suits the purpose.
3) Add a converter class, named TicketAvailableToVisibilityConverter which will display the ticket image when tickets are available, and hides it when tickets are not available for a concert.
In each platform-specific project:
1) Modify the ConcertsViews data template in each platform-specific project to include the ticket image that displays when tickets are available for a concert, as well as text indicating “available”.
2) Delete ConcertDetailsPage.xaml from each platform-specific project
Next, it’s important to revisit the ConcertsViewModel class to modify the ItemClickCommand so that when a concert item is tapped, the application launches a browser and navigates to the artist’s Bandsintown page. We will accomplish this by using the LaunchUriAsync method off the Launcher object:
Last but not least, it is just as important to add a Credits section in your app to give attribution to any images obtained under the Creative Commons License. In this case, the background image used in the app must be attributed to Léa Reviron. As well, attribution should be included for any external data providers, and/or 3rd party libraries used within the app, such as the Json.NET library. In the Windows 8.1 project, this could be included as an additional App Flyout.
Credits Flyout on Windows 8.1
In the Windows Phone 8.1 project, this could be added to the About page, as part of a Pivot item or a separate Credits page. It’s up to you.
Build and Run
With all of the modifications in place, it’s time see what it looks like. Build and run the app on each platform to see if everything is displayed and working as expected.
Maroon 5 Fan Book on Windows 8.1
Concert listings from Bandsintown on Windows 8.1
As you can see, concert data is flowing into the app from the Bandsintown API. The other feeds which AppStudio wired up for us - Twitter, YouTube and Maroon 5 Blog feeds - are working as expected. Tapping a concert listing that shows tickets are available launches a new browser page and loads the concert’s ticket sales page right within the app.
Drill-down into the concerts listings page by tapping the concerts header. Now navigate back to the main page. What do you notice?
It appears that the other feeds still have their data displayed, but the concerts list is rebuilding each time you navigate back to the main page. Let’s see what the other feeds are doing that we aren’t.
RssSchema, TwitterSchema, and VideosSchema implement IEquatable and IComparable. If you take a look at ObservableCollectionExtensions class in the Common folder within the Portable Class Library, you will notice that it contains two methods: AddRangeUnique and AddSorted. All data sources call this method when loading data to first determine if the data has already been loaded. If so, then it just retrieves the collection from the AppCache. If not, it loads the data and stores the collection to the AppCache so that on the next page load it doesn’t go through the expensive operation of reloading the data unnecessarily. The goal when designing mobile apps is to keep the application running efficiently and with minimal resources. Caching data so that it does not load data needlessly from either a web service, database, or other mechanism multiple times is one of those improvements that will really make a difference in your application’s performance. This also takes care of the flash issues we were experiencing when navigating back and forth between pages.
Let’s make the necessary changes to ConcertSchema to ensure it implements IEquatable and IComparable.
In the Equals and GetHashCode methods, we will use the concert’s id as an equality check. In the CompareTo method, we will use the concert’s event datetime field as a comparison to ensure items that get added to the list are sorted by date so we can see upcoming concerts in order by concert date.
Build and run the app again and perform the same test see if concert data is being displayed from the AppCache. Do you notice that the concert listing flash is gone now when navigating between pages after the initial data load?
One Last Gotcha
In testing the app on Windows Phone 8.1, I discovered that attempting to load the concert’s event page at the Bandsintown website fails. Instead it prompts the user to install an app from the Store, but no related app is found. In attempting to simply use the built-in browser to navigate to the URL outside of the app, I am prompted with this:
So there is clearly something wrong with the way the native browser interprets the URL or the attempted redirect that is occurring on the Bandsintown end. I’ve sent off an email to Bandsintown about this issue. In the meantime, I have revamped my Windows Phone app so that users can only view concert listings in the app. They cannot navigate to the Bandsintown event page to purchase tickets. The browser just won’t load the page.
I simply removed the wiring to the ItemClickCommand from the ConcertsList Data Template in the ConcertsViews.xaml file in the Window Phone 8.1 project. When a user taps the item, no action is taken. I will revisit this once I hear back on a solution to the issue from Bandsintown.
Other than that, everything else looks good in the Windows Phone app.
Wrap-Up
Whew! That was quite the project, but then again, imagine having to develop the entire app from scratch!
With Windows AppStudio, we were able to create a pretty slick Fan App that is supported on Windows 8.1 and Windows Phone 8.1 devices. The majority of the application was automatically generated based on information we entered in the AppStudio design tool. We had to make some modifications to bring it to the homestretch, and add that coolness factor by integrating the Bandsintown API to tie in concert listings. Sure it required a little bit of effort, but the payoff is priceless!
You can download the source code for this demo from my Github account. Remember that you will need to add your own consumer key and access token for the Twitter feed to work.