[PT] Microsoft MVP Showcase

1 Dia, 25 Experts, 14 Talks Técnicas e muito Networking
Evento organizado por Microsoft MVPs de Portugal

Quando: 22 de Abril 2015

Onde: Microsoft Portugal – Rua do Fogo de Santelmo, Lisboa

O que é?  O Microsoft MVP Showcase é um evento organizado pelos Microsoft MVPs de Portugal com o objectivo de dar a conhecer o programa Microsoft MVP, quem são os MVPs em Portugal e quais as suas áreas de expertise.

Neste evento os MVP vão apresentar um conjunto de sessões, com base na sua área de especialidade, com as últimas novidades e tendências das várias plataformas que vão ser apresentadas. Iremos também promover o contacto com os participantes durante todo o evento. Vamos ter os intervalos onde podem vir falar connosco na zona “Ask the experts” para nos conhecerem e para nos colocarem as vossas questões.

Patrocínios

    
    
   

Mais informações: msmvppt.org

Curah! 2014 award – TOP 10 Featured Curators

Last week, was published the article

2014 Curah! Awards + the Week of Curah! Awards (1 Year Celebration!)

And couldn´t be more happy, because I won the Curah! 2014 – TOP 10 Featured Curators badge which represent the award for the curators with most featured curations ( in this case the top 10!).

Here is my new badge
badge

Some news released during the Connet() event

Today started the first day of the Connect(); Microsoft Visual Studio vNext & Azure, and was released some article that we should read!
Here are

[Survey] Windows Phone and Windows Store Dev Experience – 2014

As we continue to improve the Windows developer experience, the Windows Apps teams need your help.

5-10 minutes of your time can greatly help the team better understand how the WPDev community is using the Windows and Windows Phone platforms and tools. Your answers and insights will help determine what developer resources are as we continuously improve the SDK(s) and how we support the community’s needs. Additionally, the team can (and will) share top-level results from your survey responses back out to the community.

This survey is designed to take 8 minutes – depending on how much deep feedback you care to share, your mileage may vary.

Windows Developer Survey Privacy Statement (last updated: November-14-2011)
Microsoft is committed to protecting your privacy. Your responses to this survey will not be linked to any contact information previously collected by Microsoft. Your answers will be reported in aggregate with those of other respondents. This survey collects information about your response such as the Internet Protocol (IP) address through which you access the Internet and the date and time you access the survey. This information is used to help improve the survey, analyze trends, and administer the survey. Please note that this privacy statement applies only to this survey. It does not apply to other online or offline Microsoft sites, surveys, products or services.

Please contact cliff.simpkins@microsoft.com if you have any questions concerning collection and use of your personal information.

Microsoft’s Windows App Studio Beta: Submit Menu App in the Store

Scope

This article aims to show how to submit, in the Store, the Menu App created by Windows AppStudio. See more in the following articles

Introduction

Publish an application in the Windows Store is the last step we need to do for have the application available in the store, but publish the application is not only to take a package and add it to the store, there are some steps we need to do.

In general, the main steps we must do are

  • Test the app in simulator or in a real device;
  • Analyse all requirements for submit an app in store;
  • Analyse the common issues in store certification;
  • Fixe any issue found in the above steps;
  • Take screenshots for submit in the store;
  • Associate the app with the Store;
  • Generate the packages;
  • Validate the package with Windows App Certification Kit;
  • Create the required artwork (logo and others images, if need)
  • Submit the package in Dev Center;
  • Fill all data about the app, like description and keywords, and define the category and age rating;
  • Add up to 8 screenshots;

Now, let’s see it in more detail.

Test the app

After the application is created each developer should test the application in simulator or in real devices, in some cases is good to test the app in different devices with different characteristics (but is not required!).

The following articles will help to run the app in simulator or in devices

For Windows AppStudio apps is recommended to see the following video for help in the sideloading process: Generating, Sideloading, and Publishing Windows App Studio 8.1 apps for Tablets and PCs.

Sometimes couldn´t be easy to test our application or we don´t know what to test, a simple and good test is to provide the package to our friends or beta testers for they provide a feedback about the app, normally they saw issues that the developer not see. But before it, is recommended that each developer should do the basic tests provided in the following article Testing apps for Windows Phone 8.

In the article Testing apps for Windows Phone 8, we can find the App certification requirements for Windows Phone that are very important! If our app not respect this requirements the application will fail the certification and we should be updated about the changes in these requirements, for see the last changes read the article the App certification requirements change history for Windows Phone and finally we could read the Top Windows Phone app certification failures and how to avoid them. For Windows apps, you should read App certification requirements for the Windows Store and the common certification failures.

Each issue we find based in tests should be fixed and a new version should be created for apply new tests. After the app looks great you can skip to next step.

Take the screenshots

The next step is to take the screenshots that are required and this screenshots will showed to the user, and we only can upload up to 8 screenshots. For take the screenshots we can use the simulator, because it has a great feature for it, we only need to deploy the app in simulator as following

When we click in “Capture” button, the screenshot is taken and the image is save in a folder we defined.

Associate the app with the Store and generate packages

We can associate the app to the store and for it there are two ways: associate in Windows AppStudio or associate in Visual Studio.

In Windows AppStudio

The last step before generate the app (in Windows AppStudio) is the Publish, where the user can define the app title, the app description, the language, allow to connect the app with the store. The following screen show the Publish separator

In Publish separator (we saw above), click in “Associate App with the Store”, it will show the following form

For fill this form, we should open the Dashboard in Windows Phone Dev Center or in Windows Dev Center for get the information about our account (Publisher GUID, Publisher name)

And in the Dashboard we will find the Account option.

The information about the Menu App (App identity and App display name) is got after we create the application in dashboard, by clicking in Submit App.

Then we will have

At the end, we will have

After save all, it’s time to generate the app, for it, click in finish and then Generate. Now we need to choose Publish Packages, for create the packages for the store

After it we will get

At this moment we have the packages for the store.

In Visual Studio

For how that modified the app in Visual Studio or got the source code from in Windows AppStudio, is possible to connect the app with the Store, by doing

And then need to follow the wizard

At the end we will have an xml file with the store information, like following

 

After it is possible to generate the packages, as following

 

And we will get another wizard where we can choose if the package will be for store, and at the end we can set the package version, the output folder and others

In this cases, the packages are created for submit in store and the last panel will show the output path for the package and an option for run the Windows App Certification Kit

Running Windows App Certification Kit

If we click for “Launch Windows App Certification Kit” we will see the following wizard

Windows App Certification Kit is an automatic process for verify if the app is ok and it allow to select which test we want to run, in general, we should select all!

At the end, it will show the result, if passed or not and provide a report with more details. See the complete report here: MenuApp-WindowsAppCertificationKit-Report. If the app do not passe these tests, we should not submit the app in store until the issues reported in report are not fixed.

Note: One app that passed in this test can fail in others tests that this test do not test, but if the app not passed in these tests will not pass in store, too. For get more information about it, see the article Using the Windows App Certification Kit.

The artwork

Before go to the Dev Center for submit the app, we should prepare all artwork. The screenshots are taken, the app title icon with 300×300 should be created and if need create the background image with 1000×800, square icon with 358×358 and wide icon with 358×173.

Is recommended to see this App submission checklist which help to prepare and organize all the required info.

Uploading packages

Now is time to upload the package and fill the required data (description, keywords,…)

Choose the option 2, click “add new” and then choose the package

It will be uploaded and will showed the package name, version, package details

A form for description, keywords

 

And the options for add the artwork

Note:

  1. This form need to be defined for each language supported.
  2. If for some reason you get any issue when upload the packages, see the article Resolving package upload errors.

At this moment all data was filled and the app can be submitted to the certification process. If there is question about the certification process, and the different stages, we can find detailed info here.

In some cases, can be useful to add some notes to the testers (from certification process), for see how we should do it see the article Providing info to certification testers.

Now the sky is the limit and our app can be one of the top apps


For it we should promote our app, see more about in this article How to Market and Promote your apps on Windows Phone and Windows 8.

See also

[Survey] Developer tools (F12) – Customer feedback

ie

 Here’s your chance to voice your opinions about which areas of the tools you’re enjoying and what could be improved to make your IE workflow better, faster, and easier.

To show our thanks, we’re giving an Xbox One gaming console to one lucky participant. Make sure you give us your email address on the last page of the survey to enter the drawing!

Continue…

 

Authentication using Facebook, Google and Microsoft accounts in Universal Apps using MVVM

Introduction

This sample shows how to connect universal apps to Facebook, Google and Microsoft accounts using the MVVM pattern.

Building the Sample

You only need Visual Studio 2012 or Visual Studio 2013 and Windows 8 or Windows 8.1, both the RTM version.

Description

Recently published was Authentication using Facebook, Google and Microsoft account in WP8.0 App (MVVM) and this sample has the same goal, but now the target is Universal Apps. Both have the goal to use the MVVM pattern.

Before starting this sample, analize to see if the SDKs used in the first sample could be used in this new sample and in a first attempt didn´t find a package for all the targets (Windows 8.1 and Windows Phone 8.1 Runtime). Let’s see that analysis.

The packages used was:

  1. Facebook SDK for Windows Phone (http://facebooksdk.net/docs/phone/ )
  2. Google APIs Auth Client and Google APIs OAuth2 Client (https://www.nuget.org/packages/Google.Apis.Auth/ andhttps://www.nuget.org/packages/Google.Apis.Authentication/1.6.0-beta )
  3. Live SDK (http://msdn.microsoft.com/en-US/onedrive/dn630256 )

The packages that were analized are:

  1. Facebook SDK for Windows Phone: there is a package for Windows 8.1 Store Apps but there isn’t for Windows Phone 8.1 Runtime (we cannot use the version from Windows Phone 8.0 because it uses a namespace for controls that does not exist in the Windows Phone 8.1 Runtime)
  2. Google APIs Auth Client and Google APIs OAuth2 Client: there is a package compatible with Windows 8.1 Store Apps but it is a bit different from the sample created before, the API changed. And there isn’t a package for the Windows Phone 8.1 Runtime.
  3. Live SDK: is compatible with the Windows Phone 8.1 Runtime and Windows 8.1.

The next step, was to try to port the package for Google from Windows 8.1 Store Apps to Windows Phone 8.1 Runtime, create the logic because there is a lot of code shared between them and then the hard work began.

After some attempts, the code started to throw the exception NotImplementedException because theWebAuthenticationBroker class does not work the same way for these targets. There is a sample that shows this difference, here is the source code  and we will see this in this sample.

In conclusion of this analysis, I decided to use WebAuthenticationBroker for authentication using Facebook and Google accounts and Live SDK for Microsoft accounts.

Let’s start the sample!

Note: This sample uses MVVM Light and Cimbalino Toolkit.

For each provider it is necessary to get the app id/client id/client secrect in their websites.

For Google go to https://console.developers.google.com/project and create a new project (APIs and auth > credentials).

Universal Apps using MVVM

For Facebook go to https://developers.facebook.com/ and create a new app.

For Live SDK go to https://account.live.com/developers/applications/index and create one or use an existing app.

Before you start you should change the Constant file to add client ids / client secret / app id, without it the app fails!!

 

/// <summary>   
    /// Defines the constants strings used in the app.   
    /// </summary>   
    public class Constants   
    {   
        /// <summary>   
        /// The google callback url.   
        /// </summary>   
       #if !WINDOWS_PHONE_APP 
       public const string GoogleCallbackUrl = "urn:ietf:wg:oauth:2.0:oob"; 
       #else 
        public const string GoogleCallbackUrl = "http://localhost"; 
       #endif  
   
        /// <summary>   
        /// The facebook app id.   
        /// </summary>   
        public const string FacebookAppId = "<app id>";   
   
        /// <summary>   
        /// The google client identifier.   
        /// </summary>   
        public const string GoogleClientId = "<client id>";   
           
        /// <summary>   
        /// The google client secret.   
        /// </summary>   
        public const string GoogleClientSecret = "<client secret";   
   
        /// <summary>   
        /// The login token.   
        /// </summary>   
        public const string LoginToken = "LoginToken";   
           
        /// <summary>   
        /// The facebook provider.   
        /// </summary>   
        public const string FacebookProvider = "facebook";   
   
        /// <summary>   
        /// The google provider.   
        /// </summary>   
        public const string GoogleProvider = "google";   
   
        /// <summary>   
        /// The microsoft provider.   
        /// </summary>   
        public const string MicrosoftProvider = "microsoft";   
    }

This sample will use the same idea used in Authentication using Facebook, Google and Microsoft account in WP8.0 App (MVVM). There are classes that have the same goal and the same name. Like in that sample, this sample created a SessionService that manages the Login and Logout using a provider value. That is nice because in LoginView we set the buttons to the same command and for each command we set the provider in commandparameter. With it, the LoginView and LoginViewModel are more clear and simple.

The following are the classes created:

  • FacebookService has all code related with authentication with Facebook account;
  • MicrosoftService has all code related with authentication with Microsoft account;
  • GoogleService has all code related with authentication with Google account;
  • SessionService call the methods login or logout for the provide requested;

The Flow

To help to understood the difference in the flow in each platform some diagrams were created.

The flow for the Windows 8.1 Store apps will be:

The flow for Windows Phone 8.1 Runtime will be:

  • using Microsoft account
  • using Facebook Account or Google account

Note: Start in LoginView using the blue arrow and when the blue flow finnishes, go to FacebookService/GoogleService and follow the red flow.

Like we can see, the authentication for Windows Phone 8.1 is very complicated, it could be easier like in Windows 8.1 Store apps. And It breaks the MVVM Pattern!

This sample is a Universal App, for this reason the code can be found in the Shared Project and to add specific features for each target directives (#if #else #endif) are used, it can cause some difficulties for understanding the code but is a good way to have only one code in one place. Partial methods and classes can be used here, because in most cases directives are added to add a method for Windows Phone.

The FacebookService

/// <summary>   
    /// Defines the Facebook Service.   
    /// </summary>   
    public class FacebookService : IFacebookService   
    {   
        private readonly ILogManager _logManager;   
   
        /// <summary>   
        /// Initializes a new instance of the <see cref="FacebookService"/> class.   
        /// </summary>   
        /// <param name="logManager">   
        /// The log manager.   
        /// </param>   
        public FacebookService(ILogManager logManager)   
        {   
            _logManager = logManager;   
        }   
   
        /// <summary>   
        /// The login sync.   
        /// </summary>   
        /// <returns>   
        /// The <see cref="Task"/> object.   
        /// </returns>   
        public async Task<Session> LoginAsync()   
        {   
            const string FacebookCallbackUrl = "https://m.facebook.com/connect/login_success.html";   
            var facebookUrl = "https://www.facebook.com/dialog/oauth?client_id=" + Uri.EscapeDataString(Constants.FacebookAppId) + "&redirect_uri=" + Uri.EscapeDataString(FacebookCallbackUrl) + "&scope=public_profile,email&display=popup&response_type=token";   
   
            var startUri = new Uri(facebookUrl);   
            var endUri = new Uri(FacebookCallbackUrl);   
  
#if WINDOWS_PHONE_APP   
            WebAuthenticationBroker.AuthenticateAndContinue(startUri, endUri, null, WebAuthenticationOptions.None);   
            return null;   
#else   
            var webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, startUri, endUri);   
            return GetSession(webAuthenticationResult);   
#endif   
        }   
           
        private void GetKeyValues(string webAuthResultResponseData, out string accessToken, out string expiresIn)   
        {   
            string responseData = webAuthResultResponseData.Substring(webAuthResultResponseData.IndexOf("access_token", StringComparison.Ordinal));   
            string[] keyValPairs = responseData.Split('&');   
            accessToken = null;   
            expiresIn = null;   
            for (int i = 0; i < keyValPairs.Length; i++)   
            {   
                string[] splits = keyValPairs[i].Split('=');   
                switch (splits[0])   
                {   
                    case "access_token":   
                        accessToken = splits[1];   
                        break;   
                    case "expires_in":   
                        expiresIn = splits[1];   
                        break;   
                }   
            }   
        }   
   
        /// <summary>   
        /// This function extracts access_token from the response returned from web authentication broker   
        /// and uses that token to get user information using facebook graph api.    
        /// </summary>   
        /// <param name="accessToken">   
        /// The access Token.   
        /// </param>   
        /// <returns>   
        /// The <see cref="Task"/>.   
        /// </returns>   
        private async Task<UserInfo> GetFacebookUserNameAsync(string accessToken)   
        {   
            var httpClient = new HttpClient();   
            var response = await httpClient.GetStringAsync(new Uri("https://graph.facebook.com/me?access_token=" + accessToken));   
            var value = JsonValue.Parse(response).GetObject();   
            var facebookUserName = value.GetNamedString("name");   
   
            return new UserInfo   
            {   
                Name = facebookUserName,   
            };   
        }   
   
        /// <summary>   
        /// Logouts this instance.   
        /// </summary>   
        public async void Logout()   
        {   
            Exception exception = null;   
            try   
            {   
                  
            }   
            catch (Exception ex)   
            {   
                exception = ex;   
            }   
            if (exception != null)   
            {   
                await _logManager.LogAsync(exception);   
            }   
        }   
  
#if WINDOWS_PHONE_APP   
        public async Task<Session> Finalize(WebAuthenticationBrokerContinuationEventArgs args)   
        {   
            Exception exception = null;   
            try   
            {   
                var result = args.WebAuthenticationResult;   
   
                return GetSession(result);   
            }   
            catch (Exception e)   
            {   
                exception = e;   
            }   
   
            await _logManager.LogAsync(exception);   
              
            return null;   
        }   
#endif   
        private Session GetSession(WebAuthenticationResult result)   
        {   
            if (result.ResponseStatus == WebAuthenticationStatus.Success)   
            {   
                string accessToken;   
                string expiresIn;   
                GetKeyValues(result.ResponseData, out accessToken, out expiresIn);   
   
                return new Session   
                {   
                    AccessToken = accessToken,   
                    ExpireDate = new DateTime(long.Parse(expiresIn)),   
                    Provider = Constants.FacebookProvider   
                };   
            }   
            if (result.ResponseStatus == WebAuthenticationStatus.ErrorHttp)   
            {   
                throw new Exception("Error http");   
            }   
            if (result.ResponseStatus == WebAuthenticationStatus.UserCancel)   
            {   
                throw new Exception("User Canceled.");   
            }   
            return null;   
        }   
    }

In this class, in LoginAsync, we could see the directives that define the code for each platform. The first attempt was a bit complicated to define a solution for it, using null was the solution (for Windows Phone, of course!). This class doesn´t do anything in the logout method, we could remove it, but to keep the same pattern in all the classes it wasn´t removed and the session is not saved in webview, at least it is possible to login using a different account when the LoginView is shown again.

The GoogleService

public class GoogleService : IGoogleService
    {
        private readonly ILogManager _logManager;

        /// <summary>
        /// Initializes a new instance of the <see cref="GoogleService"/> class.
        /// </summary>
        /// <param name="logManager">
        /// The log manager.
        /// </param>
        public GoogleService(ILogManager logManager)
        {
            _logManager = logManager;
        }

        /// <summary>
        /// The login async.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/> object.
        /// </returns>
        public async Task<Session> LoginAsync()
        {
            var googleUrl = new StringBuilder();
            googleUrl.Append("https://accounts.google.com/o/oauth2/auth?client_id=");
            googleUrl.Append(Uri.EscapeDataString(Constants.GoogleClientId));
            googleUrl.Append("&scope=openid%20email%20profile");
            googleUrl.Append("&redirect_uri=");
            googleUrl.Append(Uri.EscapeDataString(Constants.GoogleCallbackUrl));
            googleUrl.Append("&state=foobar");
            googleUrl.Append("&response_type=code");
          
            var startUri = new Uri(googleUrl.ToString());
           

#if !WINDOWS_PHONE_APP
           var endUri = new Uri("https://accounts.google.com/o/oauth2/approval?");
           var webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.UseTitle, startUri, endUri);
           return await GetSession(webAuthenticationResult);
#else
            WebAuthenticationBroker.AuthenticateAndContinue(startUri, new Uri(Constants.GoogleCallbackUrl), null, WebAuthenticationOptions.None);
            return null;
#endif
        }
        
        private string GetCode(string webAuthResultResponseData)
        {
            // Success code=4/izytpEU6PjuO5KKPNWSB4LK3FU1c
            var split = webAuthResultResponseData.Split('&');

            return split.FirstOrDefault(value => value.Contains("code"));
        }

        /// <summary>
        /// The logout.
        /// </summary>
        public void Logout()
        {
        }

#if WINDOWS_PHONE_APP
        public async Task<Session> Finalize(WebAuthenticationBrokerContinuationEventArgs args)
        {
            Exception exception = null;
            try
            {
                return await GetSession(args.WebAuthenticationResult);
            }
            catch (Exception e)
            {
                exception = e;
            }

            await _logManager.LogAsync(exception);

            return null;
        }
#endif
        private async Task<Session> GetSession(WebAuthenticationResult result)
        {
            if (result.ResponseStatus == WebAuthenticationStatus.Success)
            {
                var code = GetCode(result.ResponseData);
                var serviceRequest = await GetToken(code);

                return new Session
                {
                    AccessToken = serviceRequest.access_token,
                    ExpireDate = new DateTime(long.Parse(serviceRequest.expires_in)),
                    Id = serviceRequest.id_token,
                    Provider = Constants.GoogleProvider
                };
            }
            if (result.ResponseStatus == WebAuthenticationStatus.ErrorHttp)
            {
                throw new Exception("Error http");
            }
            if (result.ResponseStatus == WebAuthenticationStatus.UserCancel)
            {
                throw new Exception("User Canceled.");
            }
            return null;
        }

        private static async Task<ServiceResponse> GetToken(string code)
        {
            
            const string TokenUrl = "https://accounts.google.com/o/oauth2/token";

            var body = new StringBuilder();
            body.Append(code);
            body.Append("&client_id=");
            body.Append(Uri.EscapeDataString(Constants.GoogleClientId));
            body.Append("&client_secret=");
            body.Append(Uri.EscapeDataString(Constants.GoogleClientSecret));
            body.Append("&redirect_uri=");
            body.Append(Uri.EscapeDataString(Constants.GoogleCallbackUrl));
            body.Append("&grant_type=authorization_code");
            
            var client = new HttpClient();
            var request = new HttpRequestMessage(HttpMethod.Post, new Uri(TokenUrl))
            {
                Content = new StringContent(body.ToString(), Encoding.UTF8, "application/x-www-form-urlencoded")
            };
            var response = await client.SendAsync(request);
            var content = await response.Content.ReadAsStringAsync();
         
            var serviceTequest = JsonConvert.DeserializeObject<ServiceResponse>(content);
            return serviceTequest;
        }
    }

 

Here, we don´t have anything new, this is similar to the FacebookService.

Note: FacebookService and GoogleService are similar but the response and request are different for the reason that these classes are not joined.

The MicrosoftService

/// <summary>   
/// The microsoft service.   
/// </summary>   
public class MicrosoftService : IMicrosoftService   
{   
    private readonly ILogManager _logManager;   
    private LiveAuthClient _authClient;   
    private LiveConnectSession _liveSession;   
  
  
    /// <summary>   
    /// Defines the scopes the application needs.   
    /// </summary>   
    private List<string> _scopes;   
       
    /// <summary>   
    /// Initializes a new instance of the <see cref="MicrosoftService"/> class.   
    /// </summary>   
    /// <param name="logManager">   
    /// The log manager.   
    /// </param>   
    public MicrosoftService(ILogManager logManager)   
    {   
        _scopes = new List<string> { "wl.signin", "wl.basic", "wl.offline_access" };   
        _logManager = logManager;   
    }   
  
    /// <summary>   
    /// The login async.   
    /// </summary>   
    /// <returns>   
    /// The <see cref="Task"/> object.   
    /// </returns>   
    public async Task<Session> LoginAsync()   
    {   
  
        Exception exception = null;   
        try   
        {   
            _authClient = new LiveAuthClient();   
            var loginResult = await _authClient.InitializeAsync(_scopes);   
            var result = await _authClient.LoginAsync(_scopes);   
            if (result.Status == LiveConnectSessionStatus.Connected)   
            {   
                _liveSession = loginResult.Session;   
                var session = new Session   
                {   
                    AccessToken = result.Session.AccessToken,   
                    Provider = Constants.MicrosoftProvider,   
                };   
  
                return session;   
            }   
  
        }   
        catch (LiveAuthException ex)   
        {   
            throw new InvalidOperationException("Login canceled.", ex);   
        }   
  
        catch (Exception e)   
        {   
            exception = e;   
        }   
         await _logManager.LogAsync(exception);   
  
        return null;   
    }   
  
    /// <summary>   
    /// The get user info.   
    /// </summary>   
    /// <returns>   
    /// The <see cref="Task"/> object.   
    /// </returns>   
    public async Task<IDictionary<string, object>> GetUserInfo()   
    {   
  
        Exception exception = null;   
        try   
        {      
            var liveClient = new LiveConnectClient(_liveSession);   
            LiveOperationResult operationResult = await liveClient.GetAsync("me");   
  
            return operationResult.Result;   
        }   
        catch (LiveConnectException e)   
        {   
            exception = e;   
        }   
        await _logManager.LogAsync(exception);   
  
        return null;   
    }   
  
    /// <summary>   
    /// The logout.   
    /// </summary>   
    public async void Logout()   
    {   
  
        if (_authClient == null)   
        {   
            _authClient = new LiveAuthClient();   
            var loginResult = await _authClient.InitializeAsync(_scopes);   
        }   
        if (_authClient.CanLogout)   
        {   
            _authClient.Logout();   
        }   
    }   
}

This class was reused from the sample Authentication using Facebook, Google and Microsoft account in WP8.0 App (MVVM), but for it work is required to associate the app to the store.

That will result in an additional file in the project: as in the following:

Note

 

  1. These file are removed from the sample because each developer has their own.
  2. In devices that the Microsoft account is logged the application will do the login automatically.

The SessionService

/// <summary>   
/// The service session.   
/// </summary>   
public class SessionService : ISessionService   
{   
    private readonly IApplicationDataService _applicationSettings;   
    private readonly IFacebookService _facebookService;   
    private readonly IMicrosoftService _microsoftService;   
    private readonly IGoogleService _googleService;   
    private readonly ILogManager _logManager;   
       
    /// <summary>   
    /// Initializes a new instance of the <see cref="SessionService" /> class.   
    /// </summary>   
    /// <param name="applicationSettings">The application settings.</param>   
    /// <param name="facebookService">The facebook service.</param>   
    /// <param name="microsoftService">The microsoft service.</param>   
    /// <param name="googleService">The google service.</param>   
    /// <param name="logManager">The log manager.</param>   
    public SessionService(IApplicationDataService applicationSettings,   
        IFacebookService facebookService,   
        IMicrosoftService microsoftService,   
        IGoogleService googleService, ILogManager logManager)   
    {   
        _applicationSettings = applicationSettings;   
        _facebookService = facebookService;   
        _microsoftService = microsoftService;   
        _googleService = googleService;   
        _logManager = logManager;   
    }   
  
    /// <summary>   
    /// Gets the session.   
    /// </summary>   
    /// <returns>The session object.</returns>   
    public Session GetSession()   
    {   
        var expiryValue = DateTime.MinValue;   
        string expiryTicks = LoadEncryptedSettingValue("session_expiredate");   
        if (!string.IsNullOrWhiteSpace(expiryTicks))   
        {   
            long expiryTicksValue;   
            if (long.TryParse(expiryTicks, out expiryTicksValue))   
            {   
                expiryValue = new DateTime(expiryTicksValue);   
            }   
        }   
  
        var session = new Session   
        {   
            AccessToken = LoadEncryptedSettingValue("session_token"),   
            Id = LoadEncryptedSettingValue("session_id"),   
            ExpireDate = expiryValue,   
            Provider = LoadEncryptedSettingValue("session_provider")   
        };   
        _applicationSettings.LocalSettings[Constants.LoginToken] = true;   
        return session;   
    }   
  
    /// <summary>   
    /// The save session.   
    /// </summary>   
    /// <param name="session">   
    /// The session.   
    /// </param>   
    private void Save(Session session)   
    {   
        SaveEncryptedSettingValue("session_token", session.AccessToken);   
        SaveEncryptedSettingValue("session_id", session.Id);   
        SaveEncryptedSettingValue("session_expiredate", session.ExpireDate.Ticks.ToString(CultureInfo.InvariantCulture));   
        SaveEncryptedSettingValue("session_provider", session.Provider);   
        _applicationSettings.LocalSettings[Constants.LoginToken] = true;   
    }   
  
    /// <summary>   
    /// The clean session.   
    /// </summary>   
    private void CleanSession()   
    {   
        _applicationSettings.LocalSettings.Remove("session_token");   
        _applicationSettings.LocalSettings.Remove("session_id");   
        _applicationSettings.LocalSettings.Remove("session_expiredate");   
        _applicationSettings.LocalSettings.Remove("session_provider");   
        _applicationSettings.LocalSettings.Remove(Constants.LoginToken);   
    }   
  
    /// <summary>   
    /// The login async.   
    /// </summary>   
    /// <param name="provider">   
    /// The provider.   
    /// </param>   
    /// <returns>   
    /// The <see cref="Task"/> object.   
    /// </returns>   
    public async Task<bool?> LoginAsync(string provider)   
    {   
        Provider = provider;   
        Exception exception;   
        try   
        {   
            Session session = null;   
            switch (provider)   
            {   
                case Constants.FacebookProvider:   
                    session = await _facebookService.LoginAsync();   
                    break;   
                case Constants.MicrosoftProvider:   
                    session = await _microsoftService.LoginAsync();   
                    break;   
                case Constants.GoogleProvider:   
                    session = await _googleService.LoginAsync();   
                    break;   
            }   
            if (session == null)   
            {   
                return null;   
            }   
            Save(session);   
               
            return true;   
        }   
        catch (Exception ex)   
        {   
            exception = ex;   
        }   
        await _logManager.LogAsync(exception);   
  
        return false;   
    }   
  
    /// <summary>   
    /// Gets or sets the provider.   
    /// </summary>   
    /// <value>   
    /// The provider.   
    /// </value>   
    public string Provider { get; set; }   
  
    /// <summary>   
    /// The logout.   
    /// </summary>   
    public async void Logout()   
    {   
        Exception exception = null;   
        try   
        {   
            var session = GetSession();   
            switch (session.Provider)   
            {   
                case Constants.FacebookProvider:   
                    _facebookService.Logout();   
                    break;   
                case Constants.MicrosoftProvider:   
                    _microsoftService.Logout();   
                    break;   
                case Constants.GoogleProvider:   
                    _googleService.Logout();   
                    break;   
            }   
            CleanSession();   
        }   
        catch (Exception ex)   
        {   
            exception = ex;   
        }   
        if (exception != null)   
        {   
            await _logManager.LogAsync(exception);   
        }   
    }   
  
WINDOWS_PHONE_APP   
    public async Task<bool> Finalize(WebAuthenticationBrokerContinuationEventArgs args)   
    {   
        Exception exception = null;   
        try   
        {   
            Session session = null;   
            switch (Provider)   
            {   
                case Constants.FacebookProvider:   
                    session = await _facebookService.Finalize(args);   
                    break;   
                case Constants.GoogleProvider:   
                    session = await _googleService.Finalize(args);   
                    break;   
            }   
            Save(session);   
            return true;   
        }   
        catch (Exception e)   
        {   
            exception = e;   
        }   
        await _logManager.LogAsync(exception);   
        return false;   
    }   
if   
    /// <summary>   
    /// Loads an encrypted setting value for a given key.   
    /// </summary>   
    /// <param name="key">   
    /// The key to load.   
    /// </param>   
    /// <returns>   
    /// The value of the key.   
    /// </returns>   
    private string LoadEncryptedSettingValue(string key)   
    {   
        string value = null;   
  
        var protectedBytes = _applicationSettings.LocalSettings[key];   
        if (protectedBytes != null)   
        {   
            // todo use DataProtectionProvider   
            // byte[] valueBytes = ProtectedData.Unprotect(protectedBytes, null);   
            // value = Encoding.UTF8.GetString(valueBytes, 0, valueBytes.Length);   
            value = protectedBytes.ToString();   
        }   
  
        return value;   
    }   
  
    /// <summary>   
    /// Saves a setting value against a given key, encrypted.   
    /// </summary>   
    /// <param name="key">   
    /// The key to save against.   
    /// </param>   
    /// <param name="value">   
    /// The value to save against.   
    /// </param>   
    /// <exception cref="System.ArgumentOutOfRangeException">   
    /// The key or value provided is unexpected.   
    /// </exception>   
    private void SaveEncryptedSettingValue(string key, string value)   
    {   
        if (!string.IsNullOrWhiteSpace(key) && !string.IsNullOrWhiteSpace(value))   
        {   
            // todo use DataProtectionProvider   
            // byte[] valueBytes = Encoding.UTF8.GetBytes(value);   
            // var dataProtectionProvider = new DataProtectionProvider();             
            // // Encrypt the value by using the Protect() method.   
            // byte[] protectedBytes = await dataProtectionProvider.ProtectAsync(valueBytes);   
            _applicationSettings.LocalSettings[key] = value;   
        }   
    }   
}

This class will return null if the session is null, we need to be aware that there isn´t any error and the session is returned or if it is null, the process will be done by the Finalize method.

Here is the class diagram with all classes and interfaces created in this sample:

Now to build the User Interface and because we are using the MVVM pattern, it created a LoginViewModel to do the binding to the LoginView.

The LoginViewModel

/// <summary>   
    /// The login view model.   
    /// </summary>   
    public class LoginViewModel : ViewModelBase   
    {   
        private readonly ILogManager _logManager;   
        private readonly IMessageBoxService _messageBox;   
        private readonly INetworkInformationService _networkInformationService;   
        private readonly INavigationService _navigationService;   
        private readonly ISessionService _sessionService;   
        private bool _inProgress;   
   
        /// <summary>   
        /// Initializes a new instance of the <see cref="LoginViewModel"/> class.   
        /// </summary>   
        /// <param name="navigationService">   
        /// The navigation service.   
        /// </param>   
        /// <param name="sessionService">   
        /// The session service.   
        /// </param>   
        /// <param name="messageBox">   
        /// The message box.   
        /// </param>   
        /// <param name="networkInformationService">   
        /// The network connection.   
        /// </param>   
        /// <param name="logManager">   
        /// The log manager.   
        /// </param>   
        public LoginViewModel(INavigationService navigationService,   
            ISessionService sessionService,   
            IMessageBoxService messageBox,   
            INetworkInformationService networkInformationService,   
            ILogManager logManager)   
        {   
            _navigationService = navigationService;   
            _sessionService = sessionService;   
            _messageBox = messageBox;   
            _networkInformationService = networkInformationService;   
   
            _logManager = logManager;   
            LoginCommand = new RelayCommand<string>(LoginAction);   
        }   
   
        /// <summary>   
        /// Gets the navigation service.   
        /// </summary>   
        /// <value>   
        /// The navigation service.   
        /// </value>   
        public INavigationService NavigationService   
        {   
            get { return _navigationService; }   
        }   
   
        /// <summary>   
        /// Gets or sets a value indicating whether in progress.   
        /// </summary>   
        /// <value>   
        /// The in progress.   
        /// </value>   
        public bool InProgress   
        {   
            get { return _inProgress; }   
            set { Set(() => InProgress, ref _inProgress, value); }   
        }   
   
        /// <summary>   
        /// Gets the facebook login command.   
        /// </summary>   
        /// <value>   
        /// The facebook login command.   
        /// </value>   
        public ICommand LoginCommand { get; private set; }   
   
        /// <summary>   
        /// Facebook's login action.   
        /// </summary>   
        /// <param name="provider">   
        /// The provider.   
        /// </param>   
        private async void LoginAction(string provider)   
        {   
            Exception exception = null;   
            bool isToShowMessage = false;   
            try   
            {   
                if (!_networkInformationService.IsNetworkAvailable)   
                {   
                    await _messageBox.ShowAsync("There isn´t network connection.",   
                                          "Authentication Sample",   
                                          new List<string> { "Ok" });   
                    return;   
                }   
                if (Constants.GoogleClientId.Contains("<") || Constants.GoogleClientSecret.Contains("<"))   
                {   
                    await _messageBox.ShowAsync("Is missing the google client id and client secret. Search for Constant.cs file.",   
                                         "Authentication Sample",   
                                         new List<string> { "Ok" });   
                    return;   
                }   
                if (Constants.FacebookAppId.Contains("<"))   
                {   
                    await _messageBox.ShowAsync("Is missing the facebook client id. Search for Constant.cs file.",   
                                         "Authentication Sample",   
                                         new List<string> { "Ok" });   
                    return;   
                }   
                InProgress = true;   
                var auth = await _sessionService.LoginAsync(provider);   
                if (auth == null)   
                {   
                    return;   
                }   
                if (!auth.Value)   
                {   
                    await ShowMessage();   
                }   
                else   
                {   
                    _navigationService.Navigate<MainView>();   
                    InProgress = false;   
                }   
   
                InProgress = false;   
            }   
            catch (Exception ex)   
            {   
                InProgress = false;   
                exception = ex;   
                isToShowMessage = true;   
            }   
            if (isToShowMessage)   
            {   
                await _messageBox.ShowAsync("Application fails.",   
                                           "Authentication Sample",    
                                            new List<string> { "Ok" });   
            }   
            if (exception != null)   
            {   
                await _logManager.LogAsync(exception);   
            }   
        }   
   
        private async Task ShowMessage()   
        {   
            await _messageBox.ShowAsync("Wasn´t possible to complete the login.",   
               "Authentication Sample",   
                new List<string>   
                {   
                   "Ok"    
                });   
        }   
  
#if WINDOWS_PHONE_APP   
        public async void Finalize(WebAuthenticationBrokerContinuationEventArgs args)   
        {   
            var result = await _sessionService.Finalize(args);   
            if (!result)   
            {   
                await ShowMessage();   
            }   
            else   
            {   
                _navigationService.Navigate<MainView>();   
                InProgress = false;   
            }   
        }   
#endif   
    }

Note: In the LoginAction the parameter provider is the value of the CommandParameter received in LoginCommand, this is set in the login page.

For the final the code, let’s see the code for the page.

The LoginPage.xaml

<Page   
    x:Class="AuthenticationSample.UniversalApps.Views.LoginView"   
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"   
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"   
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
    xmlns:converters="using:Cimbalino.Toolkit.Converters"   
    mc:Ignorable="d">   
   
    <Page.DataContext>   
        <Binding Mode="OneWay"   
                 Path="LoginViewModel"   
                 Source="{StaticResource Locator}" />   
    </Page.DataContext>   
    <Page.Resources>   
        <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>   
    </Page.Resources>   
    <!--  LayoutRoot is the root grid where all page content is placed  -->   
    <Grid x:Name="LayoutRoot" Background="LightGray">   
        <Grid.RowDefinitions>   
            <RowDefinition Height="{StaticResource HeaderHeigth}" />   
            <RowDefinition Height="*" />   
        </Grid.RowDefinitions>   
   
        <!--  TitlePanel contains the name of the application and page title  -->   
        <StackPanel x:Name="TitlePanel"    
                    Margin="{StaticResource HeaderMargin}"   
                    VerticalAlignment="Center" Grid.Row="0">   
            <TextBlock  FontSize="30"    
                        Foreground="Black"   
                       Text="Login"/>   
        </StackPanel>   
   
        <!--  ContentPanel - place additional content here  -->   
        <Grid x:Name="ContentPanel"   
              VerticalAlignment="Center"   
              HorizontalAlignment="Center"   
              Grid.Row="1">   
            <Grid.RowDefinitions>   
                <RowDefinition Height="Auto" />   
                <RowDefinition Height="80" />   
                <RowDefinition Height="80" />   
                <RowDefinition Height="80" />   
                <RowDefinition Height="80" />   
            </Grid.RowDefinitions>   
            <TextBlock Grid.Row="0"    
                       FontSize="20"   
                       Foreground="Black"   
                       Text="Use your account"/>   
            <Button Grid.Row="1" Width="300"   
                    Margin="10"   
                    Command="{Binding LoginCommand}"   
                    CommandParameter="facebook"   
                    Background="{StaticResource FacebookBlueBackgroundBrush}" >   
                <StackPanel Orientation="Horizontal">   
                    <TextBlock Text="ï‚š"    
                                   VerticalAlignment="Center"   
                                   FontFamily="/Fonts/fontawesome-webfont.ttf#FontAwesome"    
                                   HorizontalAlignment="Left"/>   
                    <TextBlock Margin="10,0,0,0" Text="Facebook"    
                           HorizontalAlignment="Center"/>   
                </StackPanel>   
            </Button>   
            <Button Grid.Row="3"   
                    Margin="10" Width="300"   
                    Command="{Binding LoginCommand}"   
                    CommandParameter="microsoft"   
                    Background="{StaticResource MicrosoftBlueBackgroundBrush}" >   
                <StackPanel Orientation="Horizontal">   
                    <TextBlock Text="ï…º"   
                                   VerticalAlignment="Center"   
                                   FontFamily="/Fonts/fontawesome-webfont.ttf#FontAwesome"    
                                   HorizontalAlignment="Left"/>   
                    <TextBlock Margin="10,0,0,0" Text="Microsoft"    
                           HorizontalAlignment="Center"/>   
                </StackPanel>   
            </Button>   
            <Button Grid.Row="2" Width="300"   
                    Margin="10"   
                    Command="{Binding LoginCommand}"   
                    CommandParameter="google"   
                    Background="{StaticResource GoogleRedBackgroundBrush}" >   
                <StackPanel Orientation="Horizontal">   
                    <TextBlock Text=""   
                                   VerticalAlignment="Center"   
                                   FontFamily="/Fonts/fontawesome-webfont.ttf#FontAwesome"    
                                   HorizontalAlignment="Left"/>   
                    <TextBlock Margin="10,0,0,0" Text="Google"    
                           HorizontalAlignment="Center"/>   
                </StackPanel>   
            </Button>   
        </Grid>   
        <Grid Visibility="{Binding InProgress, Converter={StaticResource BooleanToVisibilityConverter}}"   
            Grid.Row="0"   
                   Grid.RowSpan="2">   
            <Rectangle    
                   Fill="Black"   
                   Opacity="0.75" />   
            <TextBlock    
                   HorizontalAlignment="Center"   
                   VerticalAlignment="Center"   
                   Text="Auth..." />   
            <ProgressBar IsIndeterminate="True" IsEnabled="True" Margin="0,60,0,0"/>   
        </Grid>   
   
    </Grid>   
</Page>

For use in the same page in Windows 8.1 Store apps and Windows Phone 8.1 Runtime was used some style.

The LoginView.xaml.cs

/// <summary>   
    /// An empty page that can be used on its own or navigated to within a Frame.   
    /// </summary>   
#if WINDOWS_PHONE_APP   
       public sealed partial class LoginView : Page, IWebAuthenticationContinuable   
#else   
      public sealed partial class LoginView : Page   
#endif   
    {   
        /// <summary>   
        /// Initializes a new instance of the <see cref="LoginView"/> class.   
        /// </summary>   
        public LoginView()   
        {   
            InitializeComponent();   
        }   
   
        /// <summary>   
        /// The on navigated to.   
        /// </summary>   
        /// <param name="e">   
        /// The e.   
        /// </param>   
        protected override void OnNavigatedTo(NavigationEventArgs e)   
        {   
            var viewModel = (LoginViewModel)DataContext;   
            viewModel.NavigationService.RemoveBackEntry();   
            base.OnNavigatedTo(e);   
        }   
  
#if WINDOWS_PHONE_APP   
   
        /// <summary>   
        /// Continues the web authentication.   
        /// </summary>   
        /// <param name="args">The <see cref="Windows.ApplicationModel.Activation.WebAuthenticationBrokerContinuationEventArgs"/> instance containing the event data.</param>   
        public void ContinueWebAuthentication(Windows.ApplicationModel.Activation.WebAuthenticationBrokerContinuationEventArgs args)   
        {   
            var viewModel = (LoginViewModel)DataContext;   
            viewModel.Finalize(args);   
        }   
#endif   
    }

Conclusion

In conclusion, the flow is completely different for each platform and it has some impact in the development and in sharing the code. Maybe, for this reason there isn’t any package for Windows Phone 8.1 that uses authentication.

Source Code

The source code can be found here.

Source Code Files

  • IFacebookService interface for FacebookService
  • IGoogleService interface for GoogleService
  • ILogManager interface for LogManager
  • IMicrosoftService interface for MicrosoftService
  • ISessionProvider interface for all providers interface (common methods)
  • ISessionService for SessionService
  • Session class for save the information about the session (provider, token, expired date)
  • FacebookService class that has all logic about the login / logout using Facebook provider
  • GoogleService class that has all logic about the login / logout using Google provider
  • MicrosoftService class that has all logic about the login / logout using Microsoft provider
  • SessionService class for manage login/logout (it will use all services provides described before)
  • LoginViewModel class for binding to LoginView.xaml
  • LoginView class that represent the page for login
  • MainViewModel class for binding to MainView.xaml
  • MainView class that appear after the login is ok
  • ViewModelLocator class contains static references to all the view model in application and provides an entry point for the bindings.

The solution

Build the Sample

  1. Start Visual Studio Express 2012 for Windows 8 and select File > Open > Project/Solution.
  2. Go to the directory in which you unzipped the sample. Go to the directory named for the sample and double-click the Visual Studio Express 2012 for Windows 8 Solution (.sln) file.
  3. Press F7 or use Build > Build Solution to build the sample.

Note: you can use Visual Studio 2013 in Windows 8.1.

Run the sample

To debug the app and then run it, press F5 or use Debug > Start Debugging. To run the app without debugging, press Ctrl+F5 or use Debug > Start Without Debugging

Output

The output for each target is:

  • Windows 8.1 Store App

Login Page

Microsoft Authentication

Facebook Authentication

Google Authentication

  • Windows Phone 8.1 App

Login View

Facebook Authentication

Google Authentication

 

Creating Windows Phone and Window 8.1 applications using Microsoft App Studio

 

This article aims to present the Microsoft App Studio for creating applications for Windows Phone 8.1 and Windows 8.1.

A few months ago Microsoft released Windows Phone App Studio Beta, a service that allows any person without programming skills to can create applications for Windows Phone in just 4 steps: have an idea, add content, choose style and use the application. Recently, more specifically in the Microsoft //Build/ event, that took place last April, a new version of the service was released alongside the beta version of Windows App Studio, which in addition to the Windows Phone applications, allows the creation of Windows 8.1 applications.

The service can be accessed from appstudio.windowsphone.com. To start with this service, the user is required to have an Outlook.com account or, in case the user doesn’t have an account of these, any Microsoft Id will work. For accounts that not fits with theses, the email account can be associated with Microsoft Id, and for it the user should use the link http://bit.ly/1gywtmO or in login page, click in Sign up.

 

The first time we do the login, the website will show a screen for allow the App Studio to access our account, which can be changed later if we wish to. After this, we need to accept the terms of use and we need to define the user for the email account we are using.

At this moment, we are ready for start creating application! For it we only need to click the button “Start new project”.

 

App Studio provides a set of templates for help the users in creating application. Theses templates are application demos for a specific context which are more used.

 

 

Noteworthy is that all the templates are C # / XAML applications and are available for both Windows Phone 8.1 and Windows 8.1, except for the Web App Template which is only available for Windows Phone.

When selecting a template of type “Empty App” we are creating an application from scratch. This template is often used when the other templates do not meet the needs of the user or for more advanced users who already have some experience with App Studio.

The user will set all kinds of content, styles and will have to use all your creativity to build a “great app”. In the case of the “Web App Template” the user will also create the application from scratch, but in this case is given a base Url which will be the starting point of the application and have access to some buttons on “AppBar”, this template is ideal for website that suits to the mobile devices. On the other hand, other templates allow to have a quick guide
in the application we are building and we only have to change the data and customize the application.

 

Now, let’s see in practice how we create applications with these templates.

 

Contoso Ltd Template

After we select the template, a screen will be shown where we can have a first look at the app. This is a simple simulation the app for Windows Phone and Windows 8.1 that does not allow to navigate to the details pages.

 

This screen allows us to have an idea about the application without installing it. Let’s see the configuration for this template.

 

Content

The first page shows the application name and logo (left, at the top) and shows all definitions for the content of the app, which, in this case, has five sections:

  • About us is an HTML section
  • Catalogue is a dynamic collection section
  • Team is a dynamic collection section
  • News is a Bing section
  • Contact us is a menu section which has menu actions

There’s a limit of up to six sections. After each section is created we can edit, delete or move the section position with the goal to define the best order for it.

For each section we can select one of the following options:

  • RSS – A list of sets of information based on an RSS feed that you enter when creating the data source.
  • Html – A single page of static text that you enter.
  • Youtube – A list of videos with titles and descriptions based on a YouTube channel or search that you enter when creating the data source.
  • Flickr – A list of images and their corresponding data based on a Flickr UserId or search that you enter when creating the data source.
  • Bing – A list of news
  • Facebook – A Facebook feed from a public Facebook page.
  • Instagram – a Instragram feed based in a tag
  • Menu – allow to create menu action which can use other apps (for example: using an address for Here Maps, using a phone number for make a call phone, and others)
  • Collection – A list of items with columns of characteristics. The collection can be static or dynamic and if the collection is dynamic the data can be imported or exported for a CSV file.

A future feature will be the twitter feed, but at this moment this is not available in App Studio, but was mentioned in a //build/ session on this subject.

App Studio already has a comprehensive list of data sources, allowing the user to create compelling apps. However, these data sources are based on RSS feeds which have a limited number of items and some presentation limitations

Theme

In this page, we can define the background image or the background color, define the text color and the application bar color. There are three option: custom style (using a background image), dark style and a light style. The Select button allows to define the style and then we need to save the configuration.

 

Tile

 

In the Tiles tab, we can define tiles for the application and we can select one type from the three available types: Flip Template,
Cycle Template and Icon Template. In this case was selected the Cycle Template and the respective images.

In the Splash & Lock separator, we define the images for o splash screen and for lock screen, for both apps.

This page doesn’t mention the size of the images but when we try to upload it, will be shown the allowed size if our images don´t fit those values.

 

Publish


In this page, the language for the app is defined. For now it is only possible to select one. It is possible to define the title, the description, and we can define if the app has an About page or even ads (but it requires development in Visual Studio). Before the finalize step it is possible to associate the app with the store, which requires a reserved name in Store Dashboard.

After all configuration we are available to finalize the app by clicking in Finish button.

 

Finish


 

On this page you can view the applications for each target platform (not being able to navigate) and it is possible to generate the application to get the application packages for install on each device and then get the source code. Clicking on the “Generate” button we get a screen where we can choose which application we want to generate.

 

 

We can generate for both cases, which implies two different generations. However, for a more experienced user that uses Visual Studio to test our application, it is recommend the generation for Windows 8.1, because the generated code is an “universal app” solution that consists of the Windows Application project Phone 8.1, Windows 8.1 application for the project, shared between the previous projects and also contains a project of type “portable class library” with the whole data structure.

After this step, we can get the application packages that allow to test the application in our devices, or we ca get the source code and then test the application in simulator or in a device using Visual Studio (but for it is a requirement to have the developer account). Is possible to install the application package directly in the device using the QRCode provided and is possible to share, in social network, the url for the application.

When we generate the application for Windows 8.1 we get this screen

Where we can get the package for the Windows 8.1 application and then we can use PowerShell to install it in our PC with Windows 8.1.

 

And we can get the source code, which the solution is a Universal App, whit the following structure:

 

With the source code, each application can be extended in order to add new features such as:

  • Add more resource strings (localization)
  • Add ads configuration
  • Add Twitter feed
  • Change the user interface

amongst others …

 

Web App Template

Like it was mentioned, this template is only available for Windows Phone and this is a Web App. Let’s now see in practice how we can use this template.

When we select the Web App Template we will see this page

 

As we can see, the content of this app is only a reference for a url, which is a website that supports mobile devices.

For example, this template uses the m.microsoft.com url, but we can change it for use any another url, like: booking.com, m.sapo.pt, m.vodafone.pt, amongst other references…

The definition for Theme, Tile and Publish are the same as we saw in Contoso Ltd template.

When we click in the Finish button, we will get to a page for generating the application packages and the source code. And when we click in Generator we will see this screen

 

The final result of the application, using the reference m.sapo.pt is

 

The application from App Studio should be tested in different devices to ensure that the application works propertly and is like we defined. Only after completing the tests, the application must be submited to the store. Recall that in the Publish page we had the option to connect the application to the store, and on the final page after the generation of the application is provided in the reference to submit in store. The applications generated by App Studio will be pass in certification process like an application developed by a programmer.

For more advanced users, who wish to extend the application giving new functionality, they don´t have a way to submit the changes in the App Studio. The solution is to do a “merge” between the modified source code and the new version of the application. And starting the moment the source code is changed, the user is responsible for the creation of application packages using Visual Studio

For more information about this subject, see the curation Building apps without code using AppStudio that contains articles, videos and others resources about App Studio.

 

In conclusion, the App Studio presents a quick solution to develop applications for both Windows Phone and 8.1 for Windows, and we can extend the functionality of the application through the generated source code. I’d like to point out that, despite all the associated automation, there are some limitations that should be worked out in the future, so that applications generated by the App Studio will have more quality.

 

 

Mobile Notification for any device using Azure Notification Hubs

Today I did a presentation about Notification Hubs, here is the slides I used:

The code can be find in my github account:

https://github.com/saramgsilva/NotificationHubs

Related articles:

[Azure] Notification Hubs – All resources you need

Microsoft Developer Tech Refresh

Microsoft Developer Tech Refresh
Event ID: 1032589842

Microsoft Lisbon Experience

Rua do Fogo de Santelmo, Lote 2.07.02
Lisboa Lisboa 1990 – 110
Portugal
Language(s): Portuguese.
Product(s): Microsoft Visual Studio, Windows, Windows Azure and Windows Phone.
Audience(s): Academic, Architect, Designer, Developer Generalist, IT Decision Maker, IT Manager, NonProfessional Developer, Pro Dev/Programmer, Tech Influencing BDM, Tech Support – Partners, Tester and Training – Partners.

Na Microsoft, trabalhamos de forma a colocar nas suas mãos as ferramentas mais poderosas para que possa criar projetos cada vez mais extraordinários, otimizados para a nova geração de devices e serviços. E, ao longo dos últimos meses, trouxemos até si grandes novidades como o Windows Phone 8.1, Universal Apps, WinJS, Visual Studio Online ou ainda as novas possibilidades com o Microsoft Azure. Apresentámos estas novidades nos grandes eventos internacionais como a BUILD, o Tech.Ed e mais – colocando todas as sessões ao seu dispor, online e gratuitamente.Mas queremos que possa conhecer estas novidades em detalhe, vendo estas tecnologias em ação. Foi por isso que criámos o novo

Microsoft Developer Tech Refresh. Um dia com 3 tracks distintas recheadas das melhores sessões técnicas (de participação livre, e independente) com as novidades das plataformas Microsoft que mais precisa de conhecer. Acima de tudo, um evento pensado para todos os que querem estar na linha da frente da tecnologia.E para este dia 18 de Junho preparámos uma agenda à altura das novidades apresentadas, que pode consultar abaixo.


Contamos consigo!
A Equipa Developer Experience & Evangelism
Microsoft Portugal
Agenda (em atualização):

 

Developer Track #1
Auditório Azure A

Developer Track #2
Auditório Azure B

Developer Track #3
Windows A e B

09h30
(90 mins)

Developer Tech Refresh: Keynote

Nuno Silva, Luís Calado
(Microsoft Technical Evangelists)

11h00

Intervalo para café

11h30
(60 mins)

Universal Apps development using HTML5 and WinJS

Alexandre Marreiros

Strategies for cross platform development with Visual Studio
Sérgio Viana


Mobile Push Notifications to any device with Azure Notification Hubs
Sara Silva

12h30

Almoço Livre

14h00
(60 mins)

Universal Apps development using XAML/C#
Ricardo Pinto

Connected Services: Leveraging Office 365 API in your Applications
Rodrigo Pinto

Integrating HDInsight in your Azure Apps
José António Silva

15h00

Intervalo

15h15
(60 mins)

What’s new for Windows Phone developers
Nuno Silva

Websites : What’s new?
João Pedro Martins

Connecting the World: Building Services for Connected Devices on Azure
Virgílio Esteves

16h15

Intervalo para café

16h30
(60 mins)

Web Application Development using WinJS
(to be confirmed)

Unity: Building your first 2D Game for Windows and Windows Phone

Eduardo Matos & Catarina Macedo

Building Line of Business Apps that use Active Directory for sign in
(to be confirmed)

17h30


Networking & Apps/Games “Made in Portugal” experience
Microsoft Showroom

 

Source:https://msevents.microsoft.com/CUI/EventDetail.aspx?culture=en-US&EventID=1032589842