Android and iOS developers are my new friends

If you know me, this title seems a little weird perhaps. I’m a Windows Phone fan as a developer as well as a consumer. It’s really important to keep in mind that before being a developer, you’re a consumer. For 4 years, I am fighting every day for the platform I like, sometimes taking risks, because I believe in the platform, I believe in the vision of Microsoft and I want to do my best to make this platform a nice platform to use for consumer.

So, yesterday, Microsoft announced 2 new tools, an Android app converter and an iOS app converter and you perhaps saw me in the video (seriously, Why film me at this exact moment !) applauding the ios converter.

I applauded two things:
– the technical challenge, this is not something easy and can only applaud all of the developers who worked on this. I currently work on an other converter and I know how complicated is it. Bravo guys
– Microsoft succeeds to not leak this information, I like to be surprised, I was

So, why I’m not mad

In my opinion, we make a big mistake thinking these converters are perfect: they aren’t

obi-wan

It’s ok for a small and simple apps (transit apps, tourism apps, administrative apps, etc…) but not for complicated apps, in this case, performances will be bad and buggy.

Just take an example : map control, I’m almost sure this one will not be 100% compatible or really restricted : this is one of the most hardest control to manage: multi-layers, pins, vectorial paths, etc… and it’s only one example. You will be able to display a map, but if you want to display vectorial shapes or multi-pins, it will be a little challenge. How many apps use maps? A lot! Android/iOS developers will need to adapt them code to use Bing maps instead of Google maps.

These converters will really help the platform, bringing all these interesting and simple apps but let be honest : boring to develop.

Don’t expect to have an Instagram, Spotify, Runastic, Waze, Snapchat, etc… with these converters. Candy crush is simplest to port than all these apps : cause it’s a game, all UI is managed by simple instruction to GPU + nobody said that it was easy to convert and 100% compatible.

But the good news, we will be able to have these apps for almost no cost (from local top apps):
https://play.google.com/store/apps/details?id=com.cyberwalkabout.localguide.sf
https://play.google.com/store/apps/details?id=com.dictionary.paid&hl=en
https://play.google.com/store/apps/details?id=com.yjklkj.dl.ca&hl=en
https://play.google.com/store/apps/details?id=com.cedarfair.cga&hl=en
https://play.google.com/store/apps/details?id=com.raleys.app.android&hl=en

All these apps are interesting for users, simple to develop, have only simple controls, easily portable and don’t need to be efficient (if the page loading takes 1 second instead of 0.2ms, it’s ok)

One simple example, in France, we can pay a “burger menu” at Mac Donald for only half of price, but for that, you need to use a mobile app… only available on Android & iOS. So what I prefer?

  • Pay the full price for my BigMac
  • Or pay half of the price for it with my ios/android ported app (not as smooth as a native app, with a bad UI and it will perhaps take 2 seconds to load BUT Its not important for this kind of app and I will have the same advantage than my other friends).

This is why I’m happy, for some apps, performance and design is not important, you only use them 10 seconds by month but it give you some advantages, thanks to Microsoft.

Let’s speak about an other thing: Bing Translator.

With this tool, you can translate an english text to spanish, the translation is not perfect, have some issues and you need to modify it manually but it’s perfect for simple and not complicated text.

Ok, here is how these converters are in my opinion :

myPreviousSentence.Replace(“translate”,”convert”).Replace(“text”,”app”).Replace(“english”,”android”).Replace(“spanish”,”windows phone”).

Some technical limitations

  • Android ported apps can only run on Windows 10 Mobile
  • These apps will not have access to all windows features: Cortana, Continuum, etc…
  • Not all android/ios features can be converted
  • Because iOS port uses source-code… you need all source codes, including source code of libraries you uses… so you need to link your apps to these source codes, and if a library uses on an other one, same process… Can be really boring + not all these libraries are open-source
  • for iOS, we only saw games, xib doesn’t seem to be supported (to create page and controls)

will I lose my job?

No

You’re no more a windows phone developer, you’re a windows developer : Mobile+Desktop+Xbox+Surface Hub+IOT+Hololens, only native apps can do it, you will have more customers, so more revenues for almost nothing, one code = many platforms. You will have more opportunities than before.

An other important thing is only native apps will have access to some features (IMO) : Lockscreen, geofencing, Cortana, background agents(?), NFC (perhaps for android apps), continuum, etc… and performance will be better, native apps will be very interesting for many companies. Just ask you a question: do you know a top apps made with Xamarin? Not me.

Last point, on Windows Phone 8.1, you can already develop apps using : .Net, QT, Cordova, Xamarin, HTML, it’s just one more tool for developers. Do you know the number of SDK available on Windows 7/8 to create an app ? Not me, but it’s huge, but major apps are made using XAML/WPF/WinForm, Microsoft technologies.

Conclusion

For simple apps, it will be perfect, don’t forget that some of these simple apps are very interesting apps sometimes !
Let be honest, WP developers aren’t interesting to develop this kind of apps, we like to work on complicated custom controls, tweak performances, make beautiful UI and I’m sure we have our place on this new world and Windows 10 gives us new tools, new platforms, new way to create some new awesome applications.

So let just say welcome to our new friends and enjoy windows 10.

How to test my app on phone with navigation bar and why it matters

Some Windows Phone, the Lumia 640 for the example, have no physical buttons, they use virtual buttons rendered at the botom of the screen, this part is named the navigation bar. It’s very important to test your app with these kind of devices, cause you can have some surprises on it, but it’s not necessary to use a real phone for that.

How to activate the navigation bar on emulators

It’s not easy to find, but Windows Phone emulators have an option to display Navigation Bar. This option is only available on 720p and 1080p emulators.

Click on the right arrow

Capture

Then go on the “sensors” tab (not so logical…)

Capture

And check the option “Software buttons”, then click on Apply. The emulator will reboot and display the new navigation bar instead of fake physical buttons:

Capture

Voilà! (Ⓒ Joe Belfiore)

Why is it important to test my app with this bar?

Let’s take an example:


<Page
Background="Orange">
<Page.BottomAppBar>
<CommandBar Opacity="0.7">
<AppBarButton Label="test" Icon="Accept"/>
</CommandBar>
</Page.BottomAppBar>
<Grid>
<StackPanel VerticalAlignment="Bottom">
<Rectangle Height="30" Fill="Red"/>
<Rectangle Height="30" Fill="Green"/>
<Rectangle Height="30" Fill="Pink"/>
<Rectangle Height="30" Fill="Yellow"/>
<Rectangle Height="30" Fill="Blue"/>
<Rectangle Height="30" Fill="Violet"/>
</StackPanel>

</Grid>
</Page>

With the following code

ApplicationView.GetForCurrentView().SetDesiredBoundsMode
         (ApplicationViewBoundsMode.UseCoreWindow);

The following code will display an Orange page with some color stripes at the bottom and with a semi-transparent application bar, here is the render on a classic device:

Capture

Nothing to say, the render is perfect (In my opinion, one of my most beautiful app!!)

But what happens on a phone with navigation bar? Here is a screenshot:

Capture

Obviously, there is a problem, the violet stripe is not visible as well as a part of the blue one.

This problem is related to ApplicationViewBoundsMode.UseCoreWindow, this command ignores all native chrome including:

  • system tray
  • application bar
  • but also navigation bar and phone call prompt.

So on our case, the page is displayed under the navigation bar, this is why a part of our page is missing

We will see how to solve it in an upcoming article

Comment traquer les exceptions avec Application Insights

Application Insights (pour Azure) est le nouvel outil d’analytique et de suivi de vos applications/sites de Microsoft. Etant un habitué de Flurry et de Google Analytics, j’ai tenté tout de même de le tester dans une de mes applications sans forcément beaucoup de conviction à la base… et pourtant !

Avouons le tout de suite, le départ de cet outil a été un gros ratage,  Visual Studio proposait d’activer le suivi via Application Insights alors que ce dernier n’avait même pas d’interface web… qui est arrivé des mois plus tard!

Toutefois, il ne faut jamais s’arrêter à sa première impressions et redonner une chance à l’outil. Après quelques jours de tests en condition réelle, je dois avouer qu’il est vraiment très très intéressant, avec notamment accès aux données temps réelles et une vraie pertinence des informations.

Toutefois, il y a encore une hic… voir même deux.

Sa documentation est très pauvre, voir confuse. Entre Application Insights pour Visual Studio Online (l’ancienne version), Application Insights pour Azure (la nouvelle version qui a peu de rapport avec la première), la version pour les sites webs, pour les apps mobiles, etc… Il est très difficile de s’y retrouver (je dirais presque que c’est pire que chercher une api WinRT sur MSDN…).

Second hic, en activant le suivi via Visual Studio on nous fait la promesse de n’avoir rien à faire et en effet, vous aurez bien le suivi des pages tout comme des sessions automatiquement, ce qui est plutôt agréable, mais il manque quelque chose… Regardons de plus près…

Capture

En effet, les crashes ne sont pas traité, pire encore, même en les envoyant manuellement via “TelemetryClient.TrackException”, rien ne se passe… Assez dommage… J’ai beau eu chercher pendant des heures sur MSDN, sur l’aide proposée par le portal, etc.., aucune infos sur le problème ou sur la façon d’activer cette fonctionnalité.

Il a dû fallu bricoler, et pour cela rien de mieux que ILSpy pour aller voir ce qui se passe dans la librairie.

On remarquera plusieurs choses, premièrement, les modules sont chargés selon un fichier de configuration que vous trouverez dans votre projet “ApplicationInsights.config”

Dans ce fichier, vous trouverez la liste des modules:


<TelemetryModules>
<Add Type="Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.DiagnosticsTelemetryModule, Microsoft.ApplicationInsights"/>
<Add Type="Microsoft.ApplicationInsights.Extensibility.Windows.SessionTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Windows"/>
<Add Type="Microsoft.ApplicationInsights.Extensibility.Windows.PageViewTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Windows"/>
</TelemetryModules>

Et en effet, on remarque qu’on a bien un module pour la gestion des sessions et des pages mais rien pour les exceptions. Analysons donc la seconde librairie nommée “Microsoft.ApplicationInsights.Extensibility.Windows”

Capture

Le voilà ! Il suffit donc de l’ajouter à la liste des modules à charger et d’espérer que tout fonctionne


<TelemetryModules>
...
<Add Type="Microsoft.ApplicationInsights.Extensibility.Windows.UnhandledExceptionTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Windows"/>
</TelemetryModules>

Et de tester en lançant quelques exceptions. Au bout de quelques secondes voici ce que vous verrez

Capture

Comme dirait notre ami Hiro Nakamura : YATTA!!!!

Conclusion

Application Insights est un très bonne outil, mais malheureusement sans réelle documentation, ce qui peut représenter un vrai frein pour certain, en espérant que celle-ci s’étoffera prochainement. En attendant, n’oubliez pas de rajouter manuellement la ligne :


<TelemetryModules>
...
<Add Type="Microsoft.ApplicationInsights.Extensibility.Windows.UnhandledExceptionTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Windows"/>
</TelemetryModules>

à vos fichiers de configuration et de tester Application Insights!

How to add IsVisible property to all WinRT UI elements

During several events, I’ve heard developers complain about the Visibility property of a UIElement cause it’s an enumeration and not a simple boolean.

Well, I understand this request, which can simplify the life of developers by avoiding large numbers of IValueConverter. But first, history!

Why Visibility isn’t a boolean?

This choice is inherited from WPF where a third value exists : ‘Hidden’. Hidden value allows to add the element to the visual tree but not displaying it (equivalent to a Opacity = 0 and Visibility = Visible). To sum up:

  • Visible: Display the element.
  • Hidden: Do not display the element, but reserve space for the element in layout.
  • Collapsed: Do not display the element, and do not reserve space for it in layout.

Having said that, I largely understand this need, being the first to grousing.

Here is a small class that will allow you to do more play with the Visibility property but with a custom attached property of type Boolean named IsVisible.

 


using System;
using Windows.UI.Xaml;

namespace Huyn
{
public class Extension : DependencyObject
{
public static readonly DependencyProperty IsVisibleProperty =
DependencyProperty.RegisterAttached(
"IsVisible",
typeof(bool),
typeof(Extension),
new PropertyMetadata(true,IsVisibleCallback)
);

private static void IsVisibleCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((UIElement) d).Visibility = (bool) e.NewValue ? Visibility.Visible : Visibility.Collapsed;
}

public static void SetIsVisible(UIElement element, bool value)
{
element.SetValue(IsVisibleProperty, value);
}

public static bool GetIsVisible(UIElement element)
{
return (bool)element.GetValue(IsVisibleProperty);
}
}

}

 

And it’s done, you can now use IsVisible on your XAML or your code-behind:

 


<Page
x:Class="IsVisibleSample.MainPage"
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:ext="using:Huyn"
mc:Ignorable="d">

<Rectangle Height="100" Width="100" Fill="Red" x:Name="Rectangle"
ext:Extension.IsVisible="false"/>
</Page>

You can use bindings:


<CheckBox x:Name="MyCheckBox" IsChecked="True" Content="show rectangle"/>
<Rectangle Height="100" Width="100" Fill="Red" x:Name="Rectangle"
ext:Extension.IsVisible="{Binding IsChecked,ElementName=MyCheckBox}"/>

or use IsVisible as the source of a binding


<CheckBox IsChecked="{Binding (ext:Extension.IsVisible),ElementName=Rectangle}"
IsEnabled="False"
Content="rectangle is visible?"/>

One more thing, on code-behind:

var val=Extension.GetIsVisible(Rectangle);
Extension.SetIsVisible(Rectangle,true);

Download the sample here

Click me!

 

License

This work is free. You can redistribute it and/or modify it under the
terms of the Do What The Fuck You Want To Public License, Version 2. See http://www.wtfpl.net/ for more details.

Comment récupérer la taille du clavier sur un téléphone 8.1 ? La suite…

Les choses changent, tout comme Windows Phone.

Depuis la première beta de windows phone 8.1, le clavier a été modifié légèrement, notamment sa hauteur afin de proposer une bonne expérience utilisateur avec le swipe. Voici donc une mise à jour du helper que j’avais proposé il y a quelques mois, avec en bonus la prise en compte du mode Landscape.

Une grosse différence par rapport à auparavant, la hauteur de l’application bar est beaucoup plus variante et dépend directement de la taille de l’écran et son PPI.

Pour l’anecdote, en testant sur l’ensemble des téléphones existants, j’ai découvert que la zone de suggestion du clavier est égale à la hauteur de l’application bar (en mode 8.1) moins 3 pixels (le haut du clavier).

Voici donc le code mis à jour:


public class PhoneSizeUtils
{
static PhoneSizeUtils()
{
var appbar = new ApplicationBar() { Opacity = 0 };
ApplicationBarHeightStatic = appbar.DefaultSize;
ApplicationBarMiniHeightStatic = appbar.MiniSize;
KeyboardPortraitHeightStatic = 339;
KeyboardLandscapeHeightStatic = 403;

try
{
var version81 = new Version(8, 1);
if (version81 <= System.Environment.OSVersion.Version)
{

object sizeobject;
if (DeviceExtendedProperties.TryGetValue("PhysicalScreenResolution", out sizeobject))
{
var screenResolution = (Size) sizeobject;

object dpiobjet;
if (DeviceExtendedProperties.TryGetValue("RawDpiY", out dpiobjet))
{
var dpi = (double) dpiobjet;
if (dpi > 0)
{
var screenDiagonal = Math.Sqrt(Math.Pow(screenResolution.Width/dpi, 2) +
Math.Pow(screenResolution.Height/dpi, 2));
if (screenDiagonal > 5)
{
ApplicationBarOpacityHeightStatic = 56;
ApplicationBarOpacityMiniHeightStatic = appbar.MiniSize;
KeyboardPortraitHeightStatic = 280;
KeyboardLandscapeHeightStatic = 214;
return;
}
}
}
}
}
ApplicationBarOpacityHeightStatic = appbar.DefaultSize;
ApplicationBarOpacityMiniHeightStatic = appbar.MiniSize;
}
finally
{
KeyboardPortraitdWithSuggestionsHeightStatic = KeyboardPortraitHeightStatic + ApplicationBarOpacityHeightStatic - 3;
KeyboardLandscapeWithSuggestionsHeightStatic = KeyboardLandscapeHeightStatic + ApplicationBarOpacityHeightStatic - 3;
}
}

public static double ApplicationBarHeightStatic;
public static double ApplicationBarMiniHeightStatic;
public static double ApplicationBarOpacityHeightStatic;
public static double ApplicationBarOpacityMiniHeightStatic;

public static double KeyboardPortraitdWithSuggestionsHeightStatic;
public static double KeyboardPortraitHeightStatic;
public static double KeyboardLandscapeWithSuggestionsHeightStatic;
public static double KeyboardLandscapeHeightStatic;

public double ApplicationBarHeight
{
get { return ApplicationBarHeightStatic; }
}

public double ApplicationBarMiniHeight
{
get { return ApplicationBarMiniHeightStatic; }
}

public double ApplicationBarOpacityHeight
{
get { return ApplicationBarOpacityHeightStatic; }
}

public double ApplicationBarOpacityMiniHeight
{
get { return ApplicationBarOpacityMiniHeightStatic; }
}

public double KeyboardPortraitdWithSuggestionsHeight
{
get { return KeyboardPortraitdWithSuggestionsHeightStatic; }
}

public double KeyboardPortraitHeight
{
get { return KeyboardPortraitHeightStatic; }
}

public double KeyboarLandscapeWithSuggestionsHeight
{
get { return KeyboardLandscapeWithSuggestionsHeightStatic; }
}

public double KeyboardLandscapeHeight
{
get { return KeyboardLandscapeHeightStatic; }
}
}

Multi-binding XAML pour WP8 et universal apps

Sans titre-2

Il semblerait que le père noël soit en avance cette année ! Après Samuel, voici mon tour pour vous faire un cadeau ! J’ai donc profité d’un de mes longs et ennuyant vols San Francisco-BreizhCity pour vous concocter cette surprise.

Les bindings complexes

Un des avantages de XAML par rapport aux autres plateformes du marché est le principe de MVVM et plus particulièrement le coeur même de celui-ci : les bindings.

Avouons qu’il serait difficile de s’en passer aujourd’hui ! Toutefois avouons aussi que par rapport aux binding de WPF, nos bindings Silverlight et WinRT font pâle-figures à côté, ceux-ci étant un peu plus limités. “C’était mieux avant”.

Imaginons donc la situation :

il faut afficher un place-holder uniquement lorsqu’une liste est vide, mais attention, il ne faut pas l’afficher non plus quand on est en train de charger des données et quand l’utilisateur n’est pas connecté.

Deux écoles existent :

La multiplication de propriétés dans le vue-modèle pour gérer chaque combinaison de propriétés élémentaires dans la vue


public bool CanDisplayPlaceholder{

get

{

return ListItems.Count==0 && CurrentUser!=null && !IsLoading;

}

}

évidemment il faudra penser à appeler PropertyChanged dès qu’une des trois propriétés est modifiés. Pour une application simple, ça va, mais pour une application complexe, cela peut être très rapidement usant et la probabilité d’oublier un cas est assez forte. De plus, à titre personnel, aimant partager mes VM entre différentes plateformes et ayant des structures de pages différents pour chacune, je n’aime pas inclure du code Vue-Only dans mes VM.

Autre solution : le gérer dans le XAML.

En général on trouve ce genre de code :

<Grid Visibility="{binding ListItems.Count, Converter={StaticResource IntToVisibilityConverter}}">
 <Grid Visibility="{binding Current, Converter={StaticResource NullableToVisibilityConverter}}">
  <Image Visibility="{binding IsLoading, Converter={StaticResource BoolToVisibilityConverter}}"/>
 </Grid>
</Grid>

Ca pique les yeux! Et encore, c’est bien pire quand il faut gérer des “ou” ou des conditions plus complexes.

Mais alors que faire ?

Comme on dit, c’est dans les vieux pots qu’on fait les meilleures soupes. Dans notre cas, le vieux pot sera WPF et la soupe le Multi-Binding !

 

Ce dernier est apparu avec WPF, faisant le bonheur des développeurs .Net, malheureusement il n’a jamais été intégré aux autres langages XAML comme Silverlight et Windows App XAML.

C’est donc le défi que je me suis lancé, et autant l’avouer, celui-ci n’était pas aisé à 12 000 mètres au dessus du sol, sans internet et avec un voisin qui semblant vouloir s’emparer mon espace vitale et un gamin devant qui souhaiterait faire une étude de résistance des matériaux en prenant comme outil de mesure l’écran de mon pc et son siège…

Techniquement, le gros défi est sur la gestion du DataContext (les éléments n’étant pas rattaché à l’arbre visuel XAML), sur la résolution du ElementName (pour les mêmes raisons) et sur les limitations fortes de la structure XAML qui malheureusement ne nous permet pas comme avec SL5 de créer ses propres balises. Mais je reviendrais sur les subtilités techniques plus tard dans un prochain article.

J’ai essayé de m’approcher au mieux de la syntaxe WPF afin de ne pas re-inventer la roue et ne pas perdre les développeurs. La seule différence est au niveau du attached property qui permet de faire la glue entre le vrai arbre XAML et notre structure de binding.

Voici donc à quoi ressemble notre code:


<TextBlock FontSize="20" TextWrapping="Wrap" Foreground="Cyan">
<mb:MultiBindingLinker.Attach>
<mb:MultiBindings>
<mb:MultiBinding TargetProperty="Text" Converter="{StaticResource ConcatMultiConverter}">
<mb:Binding Path="StringValue" />
<mb:Binding Path="Text" ElementName="ConcatTextBox1"/>
<mb:Binding Path="Text" ElementName="ConcatTextBox2" Converter="{StaticResource ToUpperCaseConverter}"/>
<mb:Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}" />
</mb:MultiBinding>
</mb:MultiBindings>
</mb:MultiBindingLinker.Attach>
</TextBlock>

La première ligne va me permettre d’attacher le binding à un élément XAML :


<mb:MultiBindingLinker.Attach>

ensuite j’y ajoute un  <mb:MultiBindings>, son rôle sera de contenir l’ensemble des multi-bindings d’un élément mais aussi, en interne, de gérer le DataContext de l’ensemble des bindings interne.

Viens ensuite l’élément important :


<mb:MultiBinding TargetProperty="Text" Converter="{StaticResource ConcatMultiConverter}">

Ce nœud va représenter un multi-binding sur une propriété précise, “Text” ici. ll est possible de lui ajouter un Converter (de type IMultiValueConverter, semblable au IValueConverter du SDK Silverlight/Winrt, mais prenant en entrée plusieurs valeurs. Il est enfin possible d’utiliser un ConverterParameter et de changer la culture du converter.

Enfin, on défini les Bindings interne :


<mb:Binding Path="Text" ElementName="ConcatTextBox2" Converter="{StaticResource ToUpperCaseConverter}"/>

 

Cet élément reprend quasi à l’identique la syntaxe du Binding classique, la première version de la librairie supporte :

– les binding classiques se basant sur le DataContext de l’élément associé

– les binding référent un élément nommé via ElementName

– les binding référent l’élément UI courant (RelativeSource=Self)

– les converters + paramètres + culture

Seul manque les autres types de RelativeSource, comme les TemplateBinding et les Ancestors, leurs supports sera ajoutés au fur et à mesure.

Conclusion

Le challenge a été très intéressant, surtout avec l’ensemble des limitations de XAML, mais le résultat est plutôt concluant et je l’espère, vous sera très utile. J’essayerais d’écrire une vraie documentation dans les prochains jours.

En attendant, vous pouvez télécharger les librairies via Nuget : https://www.nuget.org/packages/XAML-MultiBinding

tout comme le code source et les samples WP8 et universal app WP8.1+W8.1 :

http://multibinding.codeplex.com/

Soumettre ses mises à jour plus rapidement

Voici une petite astuce du jour pour les “serial-soumetteur d’apps”.

Lorsque l’on créé un package appx avec visual studio pour une application Windows Phone 8.1 ou pour Windows, Visual nous demande de nous authentifier via son compte Microsoft ainsi que de saisir un code qui a été envoyé par mail/sms afin de certifier le compte. Cette authentification 2-step est par défaut, quelque soit vos paramètres de sécurité.

En discutant avec pas mal de développeurs, je me suis rendu compte que je n’étais pas le seul à pester contre cette authentification car les sms/emails mettent parfois plus d’un minute à arriver (et c’est long quand on attend devant son pc !)

L’astuce du jour est donc de se passer des sms/emails et donc de leurs latences en utilisant directement une application sur son tel. Pour résumer, au lieu d’attendre votre sms/email, vous n’aurez qu’à lancer une application qui va vous donner directement le code à saisir, gros gain de temps !

Sans titre-1

Trois notes importantes :

  • si votre téléphone n’a plus de batterie, vous pourrez toujours utiliser les anciennes méthodes
  • votre téléphone n’a pas besoin d’avoir un accès internet pour vous fournir le code, donc aucun soucis même quand vous êtes en déplacement
  • Ca ne sert à rien d’essayer de s’authentifier avec mon compte car le numéro change toutes 30 secondes 😉

Comment activer l’authentification par l’application

Pour cela, il suffit de vous rendre sur la page suivante :

https://account.live.com/proofs/Manage

et d’activer l’option : Applications de vérification d’identité

Il vous demandera alors quel type de téléphone vous avez

Capture

et vous demandera de télécharger l’application correspondante puis de scanner le qr-code affiché (depuis l’application) pour paramétrer l’app

Sans titre-2

Aide avec l’application Windows Phone

Je ne vais pas mentir, l’app Windows Phone est codé avec les pieds, mais fonctionne.

Pour ajouter un compte, appuyez sur le bouton “+”, puis cliquez directement sur le bouton appareil photo pour prendre en photo le qr-code (elle ne le scanne pas en live), l’application va alors analyser l’image et paramétrer votre compte. Cliquez sur valider et entrez sur le site internet le code à 6 chiffres qui est maintenant généré par l’app.

 

Use Flurry on a Windows 8 app & Windows Phone 8.1 app

Flurry is a popular mobile analytics service used on many ios/android and windows phone application. To be honest, I use it on all my windows phone apps.

But what about Windows 8?

If you try to add an application on the flurry website, here is what you see:

Capture

Surprise! Flurry supports BlackBerry but not Windows 8…

No… but yes

In reality, Flurry really supports Windows 8, it’s just hidden (very hidden to be honest).

Just take the Windows Phone URI:

https://dev.flurry.com/createProjectSelectPlatform.do?platformName=windowsPhone

remove “Phone”

https://dev.flurry.com/createProjectSelectPlatform.do?platformName=windows

and it will works!

Capture

once your app created, you will be able to download the SDK:

Capture

So why?

The Windows 8 SDK has been launched 2 years ago in Beta but strangely, Flurry has never released it in public, but you can use it without problem, it’s used right now on “Age of Empire” for example and other on important applications/games

Bonus

The SDK is a windows runtime component, so works without problem on windows phone 8.1 apps!

problème de FontWeight avec les apps Windows Phone 8.1

Jouer avec le poids des polices est un des points clés pour réaliser de belles applications Metro. A titre personnel, je passe énormément de temps sur ce point pour équilibrer les informations dans mes applications.

Néanmoins, j’ai été confronté à un problème récemment avec une application Windows Phone 8.1 (WinRT).

Préambule

En Silverlight, on utilisant la propriété FontFamily pour choisir le poids de la police, par exemple : “Segoe WP Semilight” ou “Segoe WP Bold”.

En WinRT, on diffère la police de son poids, en utilisant deux propriétés, FontFamily pour choisir la police et FontWeight pour spécifier son poids : Bold, Light, Semilight, etc…

Quel est le soucis ?

Prenons le code suivant :


<StackPanel>
<TextBlock  Text="Text Light" FontWeight="Light"/>
<TextBlock  Text="Text SemiLight" FontWeight="SemiLight"/>
<TextBlock  Text="Text Normal" FontWeight="Normal"/>
<TextBlock  Text="Text Semibold" FontWeight="Semibold"/>
<TextBlock  Text="Text Bold" FontWeight="Bold"/>
<TextBlock  Text="Text Black" FontWeight="Black"/>
</StackPanel>

Si on exécute ce code dans une application Windows 8.1, voici le rendu que l’on a :

Sans titre

Aucun soucis, le rendu est totalement cohérent avec ce que l’on pouvait attendre.

Essayons maintenant le même code dans une application Windows Phone 8.1 :

Capture

Gros problème, il semblerait que deux poids soient disponibles :

  • normal : utilisé pour extralight, light, semilight, normal
  • bold : utilisé pour semibold, bold et black

Ce problème est encore plus surprenant puisque le designer de visual studio/blend a le bon rendu :

Capture

Pourquoi alors ?

De toute évidence, les applications Windows Phone 8.1 utilise “Segoe UI” comme police par défaut, or, il semblerait que les devices ainsi que les émulateurs n’embarque pas cette police et donc tente de la remplacer au plus juste, dans notre cas par “Segoe WP” et “Segoe WP Bold”. Premier constat : cela est un peu embêtant pour les applications universelles…

Comment corriger cela ?

Pour corriger ce problème, on va devoir forcer “Segoe WP” comme police par défaut en lieu et place de “Segoe UI”, pour cela plusieurs façons :

Quick and dirty

Une façon très rapide pour corriger ce problème est de rajouter FontFamily=”Segoe WP” en propriété de chaque page :


<Page
x:Class="App14.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
....
mc:Ignorable="d"
FontFamily="Segoe WP">

Problème : cette solution n’est pas compatible avec la notion d’universal apps.

Solution universelle

Afin d’être compatible universal apps, on va utiliser les ThemeResources en écrivant :


<Page
x:Class="App14.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
....
mc:Ignorable="d"
FontFamily="{ThemeResource PhoneFontFamilyNormal}">

La propriété prendra donc la valeur “Segoe UI” sous Windows 8.1 et “Segoe WP” sous Windows Phone 8.1, ce qui corrigera notre problème

Mais on peut encore faire mieux.

Solution Multiverselle

Afin de ne pas devoir rajouter la propriété FontFamily à chaque page et de limiter le risque d’oubli, on va directement modifier la police par défaut de l’ensemble des Pages  en modifiant la police de la frame de l’application dans App.xaml.cs et en faisons attention de se limiter aux applications Windows Phone:


#if WINDOWS_PHONE_APP
rootFrame.FontFamily = new FontFamily("Segoe WP");
#endif

Pourtant ça fonctionne dans certain cas !!

C’est ce que je me suis dit aussi et je me suis demandé pourquoi. En effet, vous ne rencontrerez pas ce soucis dans un bouton, dans un pivot, dans une listview, etc…

Il suffit d’analyser les templates de ces contrôles pour se rendre compte rapidement de la raison. Prenons le Template du bouton pour notre étude, voici le début du Template :


<Style x:Key="ButtonStyle1" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{ThemeResource PhoneForegroundBrush}"/>
<Setter Property="Foreground" Value="{ThemeResource PhoneForegroundBrush}"/>
<Setter Property="BorderThickness" Value="{ThemeResource PhoneBorderThickness}"/>
<Setter Property="FontFamily" Value="{ThemeResource PhoneFontFamilyNormal}"/>

...

On remarque que la propriété FontFamily est surchargée avec la valeur PhoneFontFamilyNormal qui correspond à une des solutions ci-dessus.

Conclusion

Personnellement je n’arrive pas à trancher si c’est un bug de l’OS windows phone ou un oubli dans les templates par défaut de visual studio, mais dans tous les cas, je dois avouer que cela est assez gênant et pas forcément intuitif pour les développeurs

Comment récupérer la taille du clavier sur un téléphone 8.1 ?

Dans l’article précédent, je me suis concentré sur l’application bar, mais ce n’est pas la seule différence que l’on peut constater lorsque l’on exécute une application sur un téléphone 8.0 et sur un téléphone 8.1.

La taille du clavier change elle aussi, pour s’adapter aux phablets. Dans 6tag et 6sec par exemple, j’ai besoin de la taille de ce dernier pour afficher une fausse barre de suggestion au dessus du clavier, afin de proposer à l’utilisateur une liste de hashtags ou d’amis.

Il est techniquement impossible de récupérer la taille du clavier, je vais donc partager avec vous les chiffres que j’ai constaté.

La taille d’un clavier sous Windows Phone 8.0 et sur tous les téléphones 8.1 exception faite des phablets est de 339 pixels sans la barre de suggestion et 408 pixels avec celle-ci.

Sur les phablets 8.1, cette taille change et devient : 262px sans suggestions et 313px avec.

Peut-on automatiser cela ?

Bien sûr ! Et pour cela, nous allons réutiliser la classe PhoneSizeUtils que j’avais créé pour l’application bar :

Eh espérant que cela vous aidera !


namespace Huyn.Utils
{
  public class PhoneSizeUtils
    {
      static PhoneSizeUtils()
      {
          var appbar = new ApplicationBar(){Opacity = 0};
          ApplicationBarHeightStatic = appbar.DefaultSize;
          ApplicationBarMiniHeightStatic = appbar.MiniSize;
          KeyboardWithSuggestionsHeightStatic = 408;
          KeyboardHeightStatic = 339;

          var version81 = new Version(8, 1);
          if (version81 =< System.Environment.OSVersion.Version)
          {

              object sizeobject;
              if (DeviceExtendedProperties.TryGetValue("PhysicalScreenResolution", out sizeobject))
              {
                  var screenResolution = (Size)sizeobject;

                  object dpiobjet;
                  if (DeviceExtendedProperties.TryGetValue("RawDpiY", out dpiobjet))
                  {
                      var dpi = (double) dpiobjet;
                      if (dpi > 0)
                      {
                          var screenDiagonal = Math.Sqrt(Math.Pow(screenResolution.Width / dpi, 2) +
           Math.Pow(screenResolution.Height / dpi, 2));

                          if (screenDiagonal >= 5)
                          {
                              ApplicationBarOpacityHeightStatic = 56;
                              ApplicationBarOpacityMiniHeightStatic = appbar.MiniSize;
                              KeyboardWithSuggestionsHeightStatic = 313;
                              KeyboardHeightStatic = 262;
                              return;
                          }
                      }
                  }
              }
          }
    
              ApplicationBarOpacityHeightStatic = appbar.DefaultSize;
              ApplicationBarOpacityMiniHeightStatic = appbar.MiniSize;

          
      }

      public static double ApplicationBarHeightStatic;


      public static double ApplicationBarMiniHeightStatic;
      public static double ApplicationBarOpacityHeightStatic;
      public static double ApplicationBarOpacityMiniHeightStatic;
      public static double KeyboardWithSuggestionsHeightStatic;
      public static double KeyboardHeightStatic;


      public double ApplicationBarHeight
      {
          get { return ApplicationBarHeightStatic; }
      }

      public double ApplicationBarMiniHeight
      {
          get { return ApplicationBarMiniHeightStatic; }
      }

      public double ApplicationBarOpacityHeight
      {
          get { return ApplicationBarOpacityHeightStatic; }
      }

      public double ApplicationBarOpacityMiniHeight
      {
          get { return ApplicationBarOpacityMiniHeightStatic; }
      }

      public double KeyboardHeight
      {
          get { return KeyboardHeightStatic; }
      }

      public double KeyboardWithSuggestionsHeight
      {
          get { return KeyboardWithSuggestionsHeightStatic; }
      }

    }
}