Loupe

#Windows10 : Association de protocole et d’extensions de fichier améliorés pour une meilleure communication inter-apps #B2B

Dans mon précédent article je vous ai parlé d’AppService qui va faciliter la communication inter-applications Windows 10 en permettant d’héberger une sorte de web-service dans une application. Cependant ce ne sont pas les seules évolutions dans ce domaine et je vais vous présenter les autres nouveautés dans cet article.

 

Que peut t-on faire sur Windows 8.1 ?

Il était déjà possible d’associer un protocole à une application. Ouvrir une url en utilisant ce protocole depuis une application Windows ou depuis l’explorateur permettait d’activer l’application associée en lui passant des arguments. Voici un exemple lançant Skype :

var uri = new Uri("skype://0671860000", UriKind.Absolute);
Windows.System.Launcher.LaunchUriAsync(uri);

 

Cela est bien pratique mais présente quand même certaines limitations :

  • Impossible de passer beaucoup de données.
  • Impossible de donner l’accès à un fichier.
  • L’utilisateur peut choisir n’importe quelle application pour ouvrir ce protocole et pas nécessairement la votre.
  • Il est impossible de savoir si l’application a fini d’interpréter son activation.
  • L’application cible ne peut rien renvoyer facilement en retour. Il fallait soit même implémenter un protocole pour que l’application cible nous “rappelle” (Facebook utilise ce système pour l’authentification par exemple).

 

De la même façon, il est possible d’associer une extension de fichier à une application. Le fonctionnement sera exactement le même que pour le protocole avec les mêmes limitations.

 

Les nouveautés de Windows 10

La volonté de Microsoft est d’enlever ces limitations en proposant ces APIs :

  • Lancer une application bien spécifique par protocole en fournissant son nom de package
  • Lancer une application bien spécifique (ou non) par protocole en fournissant un fichier
  • Lancer une application bien spécifique (ou non) par protocole et attendre qu’elle nous retourne un objet
  • Lancer une application bien spécifique (ou non) via extension de fichier
  • Vérifier qu’une application gérant un protocole est bien installée sur le PC

 

Cela permet donc d’adresser les différentes limitations présentes dans le SDK Windows 8 et d’avoir des scénarios complets de communication inter-applications.

 

Dans le code cela donne ce genre de choses :

// Définition de variable d'aide
var protocolUri = new Uri("InfiniteSquare://", UriKind.Absolute);
var packageFamilyName = "MonIdDePackage";
var fileUri = new Uri("ms-appx:///NousAInfiniteSquare.file");
var file = await StorageFile.GetFileFromApplicationUriAsync(fileUri);
var folder = ApplicationData.Current.LocalFolder;

LauncherOptions options = new LauncherOptions();
options.TargetApplicationPackageFamilyName = packageFamilyName;

//Lancer une application bien spécifique par protocole 
// en fournissant son nom de package
bool ok = await Launcher.LaunchUriAsync(protocolUri, options);

// Lancer une application bien spécifique(ou non) 
// par protocole en fournissant un fichier
ValueSet inputData = new ValueSet();
var fileToken = SharedStorageAccessManager.AddFile(file);
inputData.Add("FileToken", fileToken);
ok = await Launcher.LaunchUriAsync(protocolUri, options, inputData);

//Lancer une application bien spécifique (ou non) 
// par protocole et attendre qu’elle nous retourne un objet
var launchResult = await Launcher.LaunchUriForResultsAsync(protocolUri, options);

//Lancer une application bien spécifique (ou non) en
// fournissant l’accès à un fichier
await Launcher.LaunchFileAsync(file, options);

// Vérifier qu’une application gérant un protocole est bien installée sur le PC
var result = await Launcher.QueryUriSupportAsync(
        protocolUri, LaunchUriType.LaunchUri, packageFamilyName);

// Lecture du résultat
var appInstalled = result == QueryUriSupportStatus.Success;
var appNotInstalled = result == QueryUriSupportStatus.AppNotInstalled;
var appUnavailable = result == QueryUriSupportStatus.AppUnavailable;
var protocolUnavailable = result == QueryUriSupportStatus.ProtocolUnavailable;

 

N’oublions pas non plus que ces fonctionnalités sont aussi présentes sur Windows Mobile (car c’est son nouveau nom) : il existe des versions “xxxAndContinueAsync” pour certaines méthodes (par exemple LaunchUriForResultsAndContinueAsync).

 

Ma nouvelle fonctionnalité préférée est bien sur la possibilité d’appeler une application bien spécifique en lui fournissant un fichier et de pouvoir attendre un résultat ! De plus le code à écrire est relativement simple et je vais vous présenter cette solution dans la suite de l’article.

ActivByProtocole

 

Activation par protocole et attente de résultat – côté “client”

Voici la partie cliente (application activant une autre application :

// Définition de variable d'aide
var protocolUri = new Uri("InfiniteSquare://", UriKind.Absolute);
var packageFamilyName = "MonIdDePackage";
var fileUri = new Uri("ms-appx:///NousAInfiniteSquare.file");
var file = await StorageFile.GetFileFromApplicationUriAsync(fileUri);

var result = await Launcher.QueryUriSupportAsync(
      protocolUri, LaunchUriType.LaunchUri, packageFamilyName);

if (result != QueryUriSupportStatus.Success)
{
    // opération non concluante
    return false;
}

// On lance une app spécifique
LauncherOptions options = new LauncherOptions();
options.TargetApplicationPackageFamilyName = packageFamilyName;

// On lui donne un fichier
ValueSet inputData = new ValueSet();
var fileToken = SharedStorageAccessManager.AddFile(file);
inputData.Add("FileToken", fileToken);

// On attends le résultat
var launchResult = await Launcher.LaunchUriForResultsAsync(
    protocolUri, options, inputData);

if (launchResult.Status != LaunchUriStatus.Success)
{
    // opération non concluante
    return false;
}

//lecture du résultat
var retourDeLautreApp = launchResult.Result
    .FirstOrDefault(k => k.Key == "Resultat").Value;

return true;

 

Activation par protocole et attente de résultat – côté “serveur”

Côté serveur, l’application implémentant le protocole, il va falloir recevoir la valeur, la lire et retourner un résultat.

 

Pour cela, on va surcharger la méthode “OnActivated” de l’application et détecter si l’application est activée via un protocole et s’il faut retourner un résultat. Si c’est le cas, on naviguera vers la page “principale” en fournissant le paramètre d’activation qu’elle utilisera.

protected override void OnActivated(IActivatedEventArgs args)
{
    if (args.Kind == ActivationKind.ProtocolForResults)
    {
        Frame rootFrame = Window.Current.Content as Frame;
        
        // Créer la frame si elle n'existe pas
        
        // navigation classique en passant le paramètre
        // d'activation
        rootFrame.Navigate(typeof(MainPage), args);

    }
    base.OnActivated(args);
}

 

 

Dans la page principale, nous allons lire le paramètre  d’activation et le stocker dans le bon type.  Ensuite, nous pourrons utiliser sa propriété “ProtocolForResultActivation” pour indiquer que l’application a terminé et renvoyer un résultat.

private ProtocolForResultsActivatedEventArgs _activationArgs;

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    // Stockage du paramètre dans le bon type
    _activationArgs = 
        e.Parameter as ProtocolForResultsActivatedEventArgs;
}

public void ReturnResult()
{
    // Création du résultat, on pourrait aussi renvoyer
    // un fichier via un token (comme à l'aller)
    var returnedData = new ValueSet();
    returnedData.Add("MonResultat", "Un objet ici");

    // On retourne le résultat à l'application originale
    _activationArgs.ProtocolForResultsOperation
        .ReportCompleted(returnedData);
}

 

 

Il est aussi nécessaire de déclarer cette gestion du protocole dans le fichier manifest de l’application en rajoutant ces lignes :

<Extensions>
  <uap:Extension Category="Windows.protocol">
    <uap:Protocol Name="InfiniteSquare">
      <uap:Logo>Assets\InfiniteSquare.png</uap:Logo>
    </uap:Protocol>
  </uap:Extension>
</Extensions>

 

Conclusion

Pleins de bonnes nouveautés pour la communication inter-app sur ce SDK Windows 10. Bien sûr il ne s’agit encore que d’une preview mais l’on voit bien que Microsoft a décider d’adresser ce problème de façon sérieuse. Cela va surement nous servir dans nos différents projets B2B. Dans un prochain article nous irons voir une autre nouveauté du SDK pour la communication entre applications d’un même éditeur.

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus