Transfert dans Xamarin.iOS
Cet article traite de l’utilisation de Handoff dans une application Xamarin.iOS pour transférer des activités utilisateur entre des applications s’exécutant sur les autres appareils de l’utilisateur.
Apple a introduit handoff dans iOS 8 et OS X Yosemite (10.10) afin de fournir un mécanisme commun pour que l’utilisateur transfère les activités démarrées sur l’un de ses appareils, vers un autre appareil exécutant la même application ou une autre application qui prend en charge la même activité.
Cet article examine rapidement l’activation du partage d’activités dans une application Xamarin.iOS et couvre en détail l’infrastructure handoff :
À propos du transfert
Le transfert (également appelé Continuité) a été introduit par Apple dans iOS 8 et OS X Yosemite (10.10) comme moyen pour l’utilisateur de démarrer une activité sur l’un de ses appareils (iOS ou Mac) et poursuivre cette même activité sur un autre de ses appareils (comme identifié par le compte iCloud de l’utilisateur).
Le transfert a été développé dans iOS 9 pour prendre également en charge de nouvelles fonctionnalités de recherche améliorées. Pour plus d’informations, consultez notre documentation améliorations de recherche.
Par exemple, l’utilisateur peut démarrer un e-mail sur son i Téléphone et poursuivre en toute transparence l’e-mail sur son Mac, avec toutes les mêmes informations de message renseignées et le curseur dans le même emplacement qu’il l’a laissé dans iOS.
Toutes vos applications qui partagent le même ID d’équipe sont éligibles à l’utilisation de Handoff pour poursuivre les activités des utilisateurs entre les applications tant que ces applications sont livrées via l’App Store iTunes ou signées par un développeur inscrit (pour Mac, Entreprise ou Applications Ad Hoc).
Toutes NSDocument
les applications basées ont UIDocument
automatiquement la prise en charge intégrée de Handoff et nécessitent des modifications minimales pour prendre en charge handoff.
Activités utilisateur continues
La NSUserActivity
classe (ainsi que quelques modifications mineures apportées à UIKit
et AppKit
) prend en charge la définition de l’activité d’un utilisateur qui peut potentiellement être poursuivie sur un autre des appareils de l’utilisateur.
Pour qu’une activité soit transmise à un autre des appareils de l’utilisateur, elle doit être encapsulée dans une instanceNSUserActivity
, marquée comme l’activité actuelle, avoir son jeu de charge utile (les données utilisées pour effectuer la continuation) et l’activité doit ensuite être transmise à cet appareil.
Le transfert passe le minimum d’informations pour définir l’activité à poursuivre, avec des paquets de données plus volumineux synchronisés via iCloud.
Sur l’appareil de réception, l’utilisateur reçoit une notification indiquant qu’une activité est disponible pour la continuation. Si l’utilisateur choisit de poursuivre l’activité sur le nouvel appareil, l’application spécifiée est lancée (si elle n’est pas déjà en cours d’exécution) et la charge utile à partir de celle-ci NSUserActivity
est utilisée pour redémarrer l’activité.
Seules les applications qui partagent le même ID d’équipe de développeur et répondent à un type d’activité donné sont éligibles pour la continuation. Une application définit les types d’activité qu’il prend en charge sous la NSUserActivityTypes
clé de son fichier Info.plist . Étant donné cela, un appareil continu choisit l’application pour effectuer la continuation en fonction de l’ID d’équipe, du type d’activité et éventuellement du titre de l’activité.
L’application de réception utilise des informations du NSUserActivity
dictionnaire pour UserInfo
configurer son interface utilisateur et restaurer l’état de l’activité donnée afin que la transition apparaisse en toute transparence pour l’utilisateur final.
Si la continuation nécessite plus d’informations que celles qui peuvent être envoyées efficacement par le biais d’un NSUserActivity
, l’application de reprise peut envoyer un appel à l’application d’origine et établir un ou plusieurs flux pour transmettre les données requises. Par exemple, si l’activité a modifié un document de texte volumineux avec plusieurs images, la diffusion en continu serait nécessaire pour transférer les informations nécessaires pour poursuivre l’activité sur l’appareil récepteur. Pour plus d’informations, consultez la section Flux de continuation de prise en charge ci-dessous.
Comme indiqué ci-dessus, NSDocument
ou UIDocument
les applications basées ont automatiquement la prise en charge intégrée de Handoff. Pour plus d’informations, consultez la section Prise en charge des applications basées sur des documents ci-dessous.
Classe NSUserActivity
La NSUserActivity
classe est l’objet principal d’un échange de transfert et est utilisé pour encapsuler l’état d’une activité utilisateur disponible pour la continuation. Une application instancie une copie de NSUserActivity
toute activité prise en charge et souhaite continuer sur un autre appareil. Par exemple, l’éditeur de document crée une activité pour chaque document actuellement ouvert. Toutefois, seul le document frontal (affiché dans la fenêtre ou l’onglet le plus haut) est l’activité actuelle et est disponible pour la continuation.
Une instance de NSUserActivity
est identifiée à la fois par ses propriétés et Title
ses ActivityType
propriétés. La UserInfo
propriété dictionnaire est utilisée pour transmettre des informations sur l’état de l’activité. Définissez la NeedsSave
propriété true
sur si vous souhaitez charger les informations d’état par le biais du NSUserActivity
délégué. Utilisez la AddUserInfoEntries
méthode pour fusionner de nouvelles données d’autres clients dans le UserInfo
dictionnaire selon les besoins pour préserver l’état de l’activité.
La classe NSUserActivityDelegate
Il NSUserActivityDelegate
est utilisé pour conserver les informations dans un NSUserActivity
UserInfo
dictionnaire à jour et synchronisées avec l’état actuel de l’activité. Lorsque le système a besoin des informations de l’activité à mettre à jour (par exemple, avant la continuation sur un autre appareil), il appelle la UserActivityWillSave
méthode du délégué.
Vous devez implémenter la UserActivityWillSave
méthode et apporter des modifications à l’objet NSUserActivity
(par UserInfo
exemple, , Title
etc.) pour vous assurer qu’elle reflète toujours l’état de l’activité actuelle. Lorsque le système appelle la UserActivityWillSave
méthode, l’indicateur NeedsSave
est effacé. Si vous modifiez l’une des propriétés de données de l’activité, vous devez la définir NeedsSave
à true
nouveau.
Au lieu d’utiliser la UserActivityWillSave
méthode présentée ci-dessus, vous pouvez éventuellement avoir UIKit
ou AppKit
gérer automatiquement l’activité de l’utilisateur. Pour ce faire, définissez la propriété de l’objet UserActivity
répondeur et implémentez la UpdateUserActivityState
méthode. Pour plus d’informations, consultez la section Prise en charge du transfert dans les répondeurs ci-dessous.
Prise en charge d’App Framework
Les deux UIKit
(iOS) et AppKit
(OS X) fournissent une prise en charge intégrée de handoff dans les NSDocument
classes , répondeur (NSResponder
UIResponder
/) et AppDelegate
les classes. Bien que chaque système d’exploitation implémente le transfert légèrement différemment, le mécanisme de base et les API sont identiques.
Activités des utilisateurs dans les applications basées sur des documents
Les applications iOS et OS X basées sur des documents prennent automatiquement en charge la prise en charge intégrée des documents. Pour activer cette prise en charge, vous devez ajouter une clé et une NSUbiquitousDocumentUserActivityType
valeur pour chaque CFBundleDocumentTypes
entrée dans le fichier Info.plist de l’application.
Si cette clé est présente, créez NSDocument
automatiquement NSUserActivity
des UIDocument
instances pour les documents iCloud du type spécifié. Vous devez fournir un type d’activité pour chaque type de document pris en charge par l’application et plusieurs types de documents peuvent utiliser le même type d’activité. Les deux NSDocument
et UIDocument
remplissent automatiquement la UserInfo
propriété de la NSUserActivity
propriété avec la valeur de leur FileURL
propriété.
Sur OS X, la NSUserActivity
gestion par AppKit
et associée aux répondeurs devient automatiquement l’activité actuelle lorsque la fenêtre du document devient la fenêtre principale. Sur iOS, pour NSUserActivity
les objets gérés par UIKit
, vous devez appeler BecomeCurrent
une méthode explicitement ou avoir la propriété du UserActivity
document définie sur un UIViewController
moment où l’application vient au premier plan.
AppKit
restaure automatiquement toutes les UserActivity
propriétés créées de cette façon sur OS X. Cela se produit si la ContinueUserActivity
méthode retourne false
ou si elle est non implémentée. Dans ce cas, le document est ouvert avec la OpenDocument
méthode du NSDocumentController
document et reçoit ensuite un RestoreUserActivityState
appel de méthode.
Pour plus d’informations, consultez la section Prise en charge des applications basées sur des documents ci-dessous.
Activités et répondeurs des utilisateurs
Les deux UIKit
et AppKit
peuvent gérer automatiquement une activité utilisateur si vous la définissez comme propriété d’un UserActivity
objet répondeur. Si l’état a été modifié, vous devez définir la NeedsSave
propriété du répondeur UserActivity
true
sur . Le système enregistre automatiquement le UserActivity
cas échéant, après avoir donné au répondeur le temps de mettre à jour l’état en appelant sa UpdateUserActivityState
méthode.
Si plusieurs répondeurs partagent une seule NSUserActivity
instance, ils reçoivent un UpdateUserActivityState
rappel lorsque le système met à jour l’objet d’activité utilisateur. Le répondeur doit appeler la AddUserInfoEntries
méthode pour mettre à jour le NSUserActivity
dictionnaire pour refléter l’état actuel de UserInfo
l’activité à ce stade. Le UserInfo
dictionnaire est effacé avant chaque UpdateUserActivityState
appel.
Pour dissocier d’une activité, un répondeur peut définir sa UserActivity
propriété null
sur . Lorsqu’une instance managée NSUserActivity
de l’infrastructure d’application n’a plus de répondeurs ou de documents associés, elle est automatiquement invalidée.
Pour plus d’informations, consultez la section Prise en charge du transfert dans les répondeurs ci-dessous.
Activités utilisateur et AppDelegate
Votre application est son point d’entrée principal lors de la gestion d’une AppDelegate
continuation de transfert. Lorsque l’utilisateur répond à une notification de transfert, l’application appropriée est lancée (si elle n’est pas déjà en cours d’exécution) et la WillContinueUserActivityWithType
méthode du AppDelegate
fichier sera appelée. À ce stade, l’application doit informer l’utilisateur que la continuation démarre.
L’instance NSUserActivity
est remise lorsque la AppDelegate
méthode 's ContinueUserActivity
est appelée. À ce stade, vous devez configurer l’interface utilisateur de l’application et poursuivre l’activité donnée.
Pour plus d’informations, consultez la section Implémentation du transfert ci-dessous.
Activation du transfert dans une application Xamarin
En raison des exigences de sécurité imposées par Handoff, une application Xamarin.iOS qui utilise l’infrastructure Handoff doit être correctement configurée dans le portail des développeurs Apple et dans le fichier projet Xamarin.iOS.
Effectuez les actions suivantes :
Connectez-vous au portail des développeurs Apple.
Cliquez sur Certificats, identificateurs et profils.
Si vous ne l’avez pas encore fait, cliquez sur Identificateurs et créez un ID pour votre application (par exemple
com.company.appname
), sinon modifiez votre ID existant.Vérifiez que le service iCloud a été case activée ed pour l’ID donné :
Enregistrez vos modifications.
Cliquez sur Le développement des profils>d’approvisionnement et créez un profil d’approvisionnement de développement pour votre application :
Téléchargez et installez le nouveau profil d’approvisionnement ou utilisez Xcode pour télécharger et installer le profil.
Modifiez vos options de projet Xamarin.iOS et vérifiez que vous utilisez le profil d’approvisionnement que vous venez de créer :
Ensuite, modifiez votre fichier Info.plist et vérifiez que vous utilisez l’ID d’application utilisé pour créer le profil d’approvisionnement :
Faites défiler jusqu’à la section Modes d’arrière-plan et case activée les éléments suivants :
Enregistrez les modifications apportées à tous les fichiers.
Avec ces paramètres en place, l’application est maintenant prête à accéder aux API Handoff Framework. Pour plus d’informations sur l’approvisionnement, consultez nos guides d’approvisionnement et d’approvisionnement de votre application .
Implémentation du transfert
Les activités utilisateur peuvent être poursuivies entre les applications signées avec le même ID d’équipe de développeur et prendre en charge le même type d’activité. L’implémentation du transfert dans une application Xamarin.iOS vous oblige à créer un objet d’activité utilisateur (dans UIKit
ou AppKit
), à mettre à jour l’état de l’objet pour suivre l’activité et poursuivre l’activité sur un appareil récepteur.
Identification des activités utilisateur
La première étape de l’implémentation de Handoff consiste à identifier les types d’activités utilisateur prises en charge par votre application et à voir quelles activités sont de bons candidats à la continuation sur un autre appareil. Par exemple : une application ToDo peut prendre en charge la modification d’éléments en tant que type d’activité utilisateur et la navigation dans la liste des éléments disponibles en tant qu’autre.
Une application peut créer autant de types d’activités utilisateur que nécessaire, une pour n’importe quelle fonction que l’application fournit. Pour chaque type d’activité utilisateur, l’application doit suivre quand une activité du type commence et se termine, et doit conserver les informations d’état à jour pour continuer cette tâche sur un autre appareil.
Les activités utilisateur peuvent être poursuivies sur n’importe quelle application signée avec le même ID d’équipe sans mappage un-à-un entre les applications d’envoi et de réception. Par exemple, une application donnée peut créer quatre types d’activités différents, qui sont consommés par différentes applications individuelles sur un autre appareil. Il s’agit d’une occurrence courante entre une version Mac de l’application (qui peut avoir de nombreuses fonctionnalités et fonctions) et des applications iOS, où chaque application est plus petite et axée sur une tâche spécifique.
Création d’identificateurs de type d’activité
L’identificateur de type d’activité est une chaîne courte ajoutée au NSUserActivityTypes
tableau du fichier Info.plist de l’application utilisé pour identifier de manière unique un type d’activité utilisateur donné. Il y aura une entrée dans le tableau pour chaque activité prise en charge par l’application. Apple suggère d’utiliser une notation de style DNS inversée pour l’identificateur de type d’activité afin d’éviter les collisions. Par exemple : com.company-name.appname.activity
pour des activités spécifiques basées sur des applications ou com.company-name.activity
pour des activités qui peuvent s’exécuter sur plusieurs applications.
L’identificateur de type d’activité est utilisé lors de la création d’une NSUserActivity
instance pour identifier le type d’activité. Lorsqu’une activité se poursuit sur un autre appareil, le type d’activité (ainsi que l’ID d’équipe de l’application) détermine l’application à lancer pour poursuivre l’activité.
Par exemple, nous allons créer un exemple d’application appelé MonkeyBrowser. Cette application présente quatre onglets, chacun avec une URL différente ouverte dans un affichage de navigateur web. L’utilisateur pourra continuer n’importe quel onglet sur un autre appareil iOS exécutant l’application.
Pour créer les identificateurs de type d’activité requis pour prendre en charge ce comportement, modifiez le fichier Info.plist et basculez vers la vue Source . Ajoutez une NSUserActivityTypes
clé et créez les identificateurs suivants :
Nous avons créé quatre nouveaux identificateurs de type d’activité, un pour chacun des onglets de l’exemple d’application MonkeyBrowser . Lorsque vous créez vos propres applications, remplacez le contenu du tableau par les identificateurs de NSUserActivityTypes
type d’activité spécifiques aux activités prises en charge par votre application.
Suivi des modifications apportées à l’activité des utilisateurs
Lorsque nous créons une instance de la NSUserActivity
classe, nous allons spécifier une NSUserActivityDelegate
instance pour suivre les modifications apportées à l’état de l’activité. Par exemple, le code suivant peut être utilisé pour suivre les modifications d’état :
using System;
using CoreGraphics;
using Foundation;
using UIKit;
namespace MonkeyBrowse
{
public class UserActivityDelegate : NSUserActivityDelegate
{
#region Constructors
public UserActivityDelegate ()
{
}
#endregion
#region Override Methods
public override void UserActivityReceivedData (NSUserActivity userActivity, NSInputStream inputStream, NSOutputStream outputStream)
{
// Log
Console.WriteLine ("User Activity Received Data: {0}", userActivity.Title);
}
public override void UserActivityWasContinued (NSUserActivity userActivity)
{
Console.WriteLine ("User Activity Was Continued: {0}", userActivity.Title);
}
public override void UserActivityWillSave (NSUserActivity userActivity)
{
Console.WriteLine ("User Activity will be Saved: {0}", userActivity.Title);
}
#endregion
}
}
La UserActivityReceivedData
méthode est appelée lorsqu’un flux de continuation a reçu des données d’un appareil d’envoi. Pour plus d’informations, consultez la section Flux de continuation de prise en charge ci-dessous.
La UserActivityWasContinued
méthode est appelée lorsqu’un autre appareil a pris le contrôle d’une activité à partir de l’appareil actuel. Selon le type d’activité, comme l’ajout d’un nouvel élément à une liste ToDo, l’application peut avoir besoin d’abandonner l’activité sur l’appareil d’envoi.
La UserActivityWillSave
méthode est appelée avant que les modifications apportées à l’activité soient enregistrées et synchronisées sur les appareils disponibles localement. Vous pouvez utiliser cette méthode pour apporter des modifications de dernière minute à la UserInfo
propriété de l’instance NSUserActivity
avant son envoi.
Création d’une instance NSUserActivity
Chaque activité que votre application souhaite fournir la possibilité de poursuivre sur un autre appareil doit être encapsulée dans une NSUserActivity
instance. L’application peut créer autant d’activités que nécessaire et la nature de ces activités dépend des fonctionnalités et fonctionnalités de l’application en question. Par exemple, une application de messagerie peut créer une activité pour créer un message et une autre pour lire un message.
Pour notre exemple d’application, un nouveau NSUserActivity
est créé chaque fois que l’utilisateur entre une nouvelle URL dans l’une des vues de navigateur web à onglets. Le code suivant stocke l’état d’un onglet donné :
public NSString UserActivityTab1 = new NSString ("com.xamarin.monkeybrowser.tab1");
public NSUserActivity UserActivity { get; set; }
...
UserActivity = new NSUserActivity (UserActivityTab1);
UserActivity.Title = "Weather Tab";
UserActivity.Delegate = new UserActivityDelegate ();
// Update the activity when the tab's URL changes
var userInfo = new NSMutableDictionary ();
userInfo.Add (new NSString ("Url"), new NSString (url));
UserActivity.AddUserInfoEntries (userInfo);
// Inform Activity that it has been updated
UserActivity.BecomeCurrent ();
Il crée un NSUserActivity
nouveau type d’activité utilisateur créé ci-dessus et fournit un titre lisible par l’utilisateur pour l’activité. Il s’attache à une instance du NSUserActivityDelegate
fichier créé ci-dessus pour surveiller les modifications d’état et informe iOS que cette activité utilisateur est l’activité actuelle.
Remplissage du dictionnaire UserInfo
Comme nous l’avons vu ci-dessus, la UserInfo
propriété de la NSUserActivity
classe est une NSDictionary
paire clé-valeur utilisée pour définir l’état d’une activité donnée. Les valeurs stockées dans UserInfo
doivent être l’un des types suivants : NSArray
, , NSDate
NSData
, NSDictionary
, NSNull
, NSNumber
, , , NSSet
, , NSString
, ou NSURL
. NSURL
les valeurs de données qui pointent vers des documents iCloud sont automatiquement ajustées afin qu’elles pointent vers les mêmes documents sur un appareil récepteur.
Dans l’exemple ci-dessus, nous avons créé un NSMutableDictionary
objet et l’avons rempli avec une seule clé fournissant l’URL que l’utilisateur a actuellement affichée sous l’onglet donné. La AddUserInfoEntries
méthode de l’activité utilisateur a été utilisée pour mettre à jour l’activité avec les données qui seront utilisées pour restaurer l’activité sur l’appareil récepteur :
// Update the activity when the tab's URL changes
var userInfo = new NSMutableDictionary ();
userInfo.Add (new NSString ("Url"), new NSString (url));
UserActivity.AddUserInfoEntries (userInfo);
Apple suggère de conserver les informations envoyées au minimum pour s’assurer que l’activité est envoyée en temps voulu à l’appareil de réception. Si des informations plus volumineuses sont requises, comme une image attachée à un document à modifier, vous devez utiliser la continuation Flux. Pour plus d’informations, consultez la section Flux de prise en charge de la continuation ci-dessous.
Poursuite d’une activité
Le transfert informe automatiquement les appareils iOS et OS X locaux qui sont à proximité physique de l’appareil d’origine et connectés au même compte iCloud, de la disponibilité des activités utilisateur continuables. Si l’utilisateur choisit de poursuivre une activité sur un nouvel appareil, le système lance l’application appropriée (en fonction de l’ID d’équipe et du type d’activité) et les informations dont la AppDelegate
continuation doit se produire.
Tout d’abord, la WillContinueUserActivityWithType
méthode est appelée afin que l’application puisse informer l’utilisateur que la continuation est sur le point de commencer. Nous utilisons le code suivant dans le fichier AppDelegate.cs de notre exemple d’application pour gérer un démarrage de continuation :
public NSString UserActivityTab1 = new NSString ("com.xamarin.monkeybrowser.tab1");
public NSString UserActivityTab2 = new NSString ("com.xamarin.monkeybrowser.tab2");
public NSString UserActivityTab3 = new NSString ("com.xamarin.monkeybrowser.tab3");
public NSString UserActivityTab4 = new NSString ("com.xamarin.monkeybrowser.tab4");
...
public FirstViewController Tab1 { get; set; }
public SecondViewController Tab2 { get; set;}
public ThirdViewController Tab3 { get; set; }
public FourthViewController Tab4 { get; set; }
...
public override bool WillContinueUserActivity (UIApplication application, string userActivityType)
{
// Report Activity
Console.WriteLine ("Will Continue Activity: {0}", userActivityType);
// Take action based on the user activity type
switch (userActivityType) {
case "com.xamarin.monkeybrowser.tab1":
// Inform view that it's going to be modified
Tab1.PreparingToHandoff ();
break;
case "com.xamarin.monkeybrowser.tab2":
// Inform view that it's going to be modified
Tab2.PreparingToHandoff ();
break;
case "com.xamarin.monkeybrowser.tab3":
// Inform view that it's going to be modified
Tab3.PreparingToHandoff ();
break;
case "com.xamarin.monkeybrowser.tab4":
// Inform view that it's going to be modified
Tab4.PreparingToHandoff ();
break;
}
// Inform system we handled this
return true;
}
Dans l’exemple ci-dessus, chaque contrôleur de vue s’inscrit auprès de la AppDelegate
méthode publique PreparingToHandoff
qui affiche un indicateur d’activité et un message indiquant à l’utilisateur que l’activité est sur le point d’être transmise à l’appareil actuel. Exemple :
private void ShowBusy(string reason) {
// Display reason
BusyText.Text = reason;
//Define Animation
UIView.BeginAnimations("Show");
UIView.SetAnimationDuration(1.0f);
Handoff.Alpha = 0.5f;
//Execute Animation
UIView.CommitAnimations();
}
...
public void PreparingToHandoff() {
// Inform caller
ShowBusy ("Continuing Activity...");
}
AppDelegate
Le ContinueUserActivity
projet sera appelé pour poursuivre l’activité donnée. Là encore, à partir de notre exemple d’application :
public override bool ContinueUserActivity (UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
// Report Activity
Console.WriteLine ("Continuing User Activity: {0}", userActivity.ToString());
// Get input and output streams from the Activity
userActivity.GetContinuationStreams ((NSInputStream arg1, NSOutputStream arg2, NSError arg3) => {
// Send required data via the streams
// ...
});
// Take action based on the Activity type
switch (userActivity.ActivityType) {
case "com.xamarin.monkeybrowser.tab1":
// Preform handoff
Tab1.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab1});
break;
case "com.xamarin.monkeybrowser.tab2":
// Preform handoff
Tab2.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab2});
break;
case "com.xamarin.monkeybrowser.tab3":
// Preform handoff
Tab3.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab3});
break;
case "com.xamarin.monkeybrowser.tab4":
// Preform handoff
Tab4.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab4});
break;
}
// Inform system we handled this
return true;
}
La méthode publique PerformHandoff
de chaque contrôleur de vue préforme réellement le transfert et restaure l’activité sur l’appareil actuel. Dans le cas de l’exemple, il affiche la même URL dans un onglet donné que l’utilisateur parcourait sur un autre appareil. Exemple :
private void HideBusy() {
//Define Animation
UIView.BeginAnimations("Hide");
UIView.SetAnimationDuration(1.0f);
Handoff.Alpha = 0f;
//Execute Animation
UIView.CommitAnimations();
}
...
public void PerformHandoff(NSUserActivity activity) {
// Hide busy indicator
HideBusy ();
// Extract URL from dictionary
var url = activity.UserInfo ["Url"].ToString ();
// Display value
URL.Text = url;
// Display the give webpage
WebView.LoadRequest(new NSUrlRequest(NSUrl.FromString(url)));
// Save activity
UserActivity = activity;
UserActivity.BecomeCurrent ();
}
La ContinueUserActivity
méthode inclut un UIApplicationRestorationHandler
appel à l’activité basée sur le document ou le répondeur. Vous devez passer un NSArray
ou plusieurs objets restaurables au gestionnaire de restauration lors de l’appel. Par exemple :
completionHandler (new NSObject[]{Tab4});
Pour chaque objet passé, sa RestoreUserActivityState
méthode est appelée. Chaque objet peut ensuite utiliser les données du UserInfo
dictionnaire pour restaurer son propre état. Par exemple :
public override void RestoreUserActivityState (NSUserActivity activity)
{
base.RestoreUserActivityState (activity);
// Log activity
Console.WriteLine ("Restoring Activity {0}", activity.Title);
}
Pour les applications basées sur des documents, si vous n’implémentez pas la ContinueUserActivity
méthode ou qu’elle retourne false
, UIKit
ou AppKit
que vous pouvez reprendre automatiquement l’activité. Pour plus d’informations, consultez la section Prise en charge des applications basées sur des documents ci-dessous.
Échec du transfert avec grâce
Étant donné que le transfert s’appuie sur la transmission d’informations entre un regroupement d’appareils iOS et OS X faiblement connectés, le processus de transfert peut parfois échouer. Vous devez concevoir votre application pour gérer ces défaillances correctement et informer l’utilisateur des situations qui surviennent.
En cas d’échec, la DidFailToContinueUserActivitiy
méthode de l’objet AppDelegate
sera appelée. Par exemple :
public override void DidFailToContinueUserActivitiy (UIApplication application, string userActivityType, NSError error)
{
// Log information about the failure
Console.WriteLine ("User Activity {0} failed to continue. Error: {1}", userActivityType, error.LocalizedDescription);
}
Vous devez utiliser l’élément fourni NSError
pour fournir des informations à l’utilisateur sur l’échec.
Application native vers le transfert du navigateur web
Un utilisateur peut souhaiter poursuivre une activité sans avoir installé une application native appropriée sur l’appareil souhaité. Dans certains cas, une interface web peut fournir les fonctionnalités requises et l’activité peut continuer. Par exemple, le compte de messagerie de l’utilisateur peut fournir une interface utilisateur de base web pour la composition et la lecture de messages.
Si l’application native connaît l’URL de l’interface web (et la syntaxe requise pour identifier l’élément donné en cours de poursuite), elle peut encoder ces informations dans la WebpageURL
propriété de l’instance NSUserActivity
. Si l’appareil de réception n’a pas d’application native appropriée installée pour gérer la continuation, l’interface web fournie peut être appelée.
Transfert du navigateur web vers une application native
Si l’utilisateur utilisait une interface web sur l’appareil d’origine et qu’une application native sur l’appareil récepteur revendique la partie domaine de la WebpageURL
propriété, le système utilisera cette application pour gérer la continuation. Le nouvel appareil reçoit une NSUserActivity
instance qui marque le type d’activité comme BrowsingWeb
et l’URL WebpageURL
que l’utilisateur a visité, le UserInfo
dictionnaire sera vide.
Pour qu’une application participe à ce type de transfert, elle doit revendiquer le domaine dans un com.apple.developer.associated-domains
droit au format <service>:<fully qualified domain name>
(par exemple : activity continuation:company.com
).
Si le domaine spécifié correspond à la valeur d’une WebpageURL
propriété, Handoff télécharge une liste d’ID d’application approuvés à partir du site web sur ce domaine. Le site web doit fournir la liste des ID approuvés dans un fichier JSON signé nommé apple-app-site-association (par exemple). https://company.com/apple-app-site-association
Ce fichier JSON contient un dictionnaire qui spécifie une liste d’ID d’application dans le formulaire <team identifier>.<bundle identifier>
. Par exemple :
{
"activitycontinuation": {
"apps": [ "YWBN8XTPBJ.com.company.FirstApp",
"YWBN8XTPBJ.com.company.SecondApp" ]
}
}
Pour signer le fichier JSON (afin qu’il ait le bon Content-Type
), application/pkcs7-mime
utilisez l’application Terminal et une openssl
commande avec un certificat et une clé émis par une autorité de certification approuvée par iOS (voir https://support.apple.com/kb/ht5012 pour obtenir une liste). Par exemple :
echo '{"activitycontinuation":{"apps":["YWBN8XTPBJ.com.company.FirstApp",
"YWBN8XTPBJ.com.company.SecondApp"]}}' > json.txt
cat json.txt | openssl smime -sign -inkey company.com.key
-signer company.com.pem
-certfile intermediate.pem
-noattr -nodetach
-outform DER > apple-app-site-association
La openssl
commande génère un fichier JSON signé que vous placez sur votre site web à l’URL apple-app-site-association . Par exemple :
https://example.com/apple-app-site-association.
L’application reçoit toute activité dont WebpageURL
le domaine est dans son com.apple.developer.associated-domains
droit d’utilisation. Seuls les protocoles et https
les http
protocoles sont pris en charge, tout autre protocole génère une exception.
Prise en charge du transfert dans les applications basées sur des documents
Comme indiqué ci-dessus, sur iOS et OS X, les applications basées sur des documents prennent automatiquement en charge le transfert de documents basés sur iCloud si le fichier Info.plist de l’application contient une CFBundleDocumentTypes
clé de NSUbiquitousDocumentUserActivityType
. Par exemple :
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>NSRTFDPboardType</string>
. . .
<key>LSItemContentTypes</key>
<array>
<string>com.myCompany.rtfd</string>
</array>
. . .
<key>NSUbiquitousDocumentUserActivityType</key>
<string>com.myCompany.myEditor.editing</string>
</dict>
</array>
Dans cet exemple, la chaîne est un concepteur d’application DNS inversé avec le nom de l’activité ajoutée. Si elles sont entrées de cette façon, les entrées de type d’activité n’ont pas besoin d’être répétées dans le NSUserActivityTypes
tableau du fichier Info.plist .
L’objet Activité utilisateur créé automatiquement (disponible via la propriété du document) peut être référencé par d’autres objets de l’application et utilisé pour restaurer l’état lors de UserActivity
la continuation. Par exemple, pour suivre la sélection d’éléments et la position du document. Vous devez définir cette propriété d’activités NeedsSave
chaque fois que l’état change et met à jour le UserInfo
dictionnaire dans la UpdateUserActivityState
méthode.true
La UserActivity
propriété peut être utilisée à partir de n’importe quel thread et est conforme au protocole KVO (Key-Value Observing), afin qu’elle puisse être utilisée pour conserver un document synchronisé lors de son déplacement et de son sortie d’iCloud. La UserActivity
propriété est invalidée lorsque le document est fermé.
Pour plus d’informations, consultez la documentation relative à l’activité utilisateur d’Apple dans la documentation sur les applications basées sur des documents.
Prise en charge du transfert dans les répondeurs
Vous pouvez associer des répondeurs (hérités d’iOS UIResponder
ou NSResponder
sur OS X) aux activités en définissant leurs UserActivity
propriétés. Le système enregistre automatiquement la UserActivity
propriété à l’heure appropriée, en appelant la méthode du UpdateUserActivityState
répondeur pour ajouter des données actuelles à l’objet Activité utilisateur à l’aide de la AddUserInfoEntriesFromDictionary
méthode.
Prise en charge des Flux de continuation
Il peut s’agir de situations où la quantité d’informations requises pour poursuivre une activité ne peut pas être transférée efficacement par la charge utile de transfert initiale. Dans ces situations, l’application de réception peut établir un ou plusieurs flux entre lui-même et l’application d’origine pour transférer les données.
L’application d’origine définit la SupportsContinuationStreams
propriété de l’instance NSUserActivity
sur true
. Par exemple :
// Create a new user Activity to support this tab
UserActivity = new NSUserActivity (ThisApp.UserActivityTab1){
Title = "Weather Tab",
SupportsContinuationStreams = true
};
UserActivity.Delegate = new UserActivityDelegate ();
// Update the activity when the tab's URL changes
var userInfo = new NSMutableDictionary ();
userInfo.Add (new NSString ("Url"), new NSString (url));
UserActivity.AddUserInfoEntries (userInfo);
// Inform Activity that it has been updated
UserActivity.BecomeCurrent ();
L’application de réception peut ensuite appeler la GetContinuationStreams
méthode de l’application NSUserActivity
dans celle-ci AppDelegate
pour établir le flux. Par exemple :
public override bool ContinueUserActivity (UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
// Report Activity
Console.WriteLine ("Continuing User Activity: {0}", userActivity.ToString());
// Get input and output streams from the Activity
userActivity.GetContinuationStreams ((NSInputStream arg1, NSOutputStream arg2, NSError arg3) => {
// Send required data via the streams
// ...
});
// Take action based on the Activity type
switch (userActivity.ActivityType) {
case "com.xamarin.monkeybrowser.tab1":
// Preform handoff
Tab1.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab1});
break;
case "com.xamarin.monkeybrowser.tab2":
// Preform handoff
Tab2.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab2});
break;
case "com.xamarin.monkeybrowser.tab3":
// Preform handoff
Tab3.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab3});
break;
case "com.xamarin.monkeybrowser.tab4":
// Preform handoff
Tab4.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab4});
break;
}
// Inform system we handled this
return true;
}
Sur l’appareil d’origine, le délégué d’activité utilisateur reçoit les flux en appelant sa DidReceiveInputStream
méthode pour fournir les données demandées pour poursuivre l’activité de l’utilisateur sur l’appareil de reprise.
Vous utiliserez un NSInputStream
pour fournir un accès en lecture seule aux données de flux et un NSOutputStream
accès en écriture seule. Les flux doivent être utilisés de manière de demande et de réponse, où l’application de réception demande plus de données et l’application d’origine la fournit. Ainsi, les données écrites dans le flux de sortie sur l’appareil d’origine sont lues à partir du flux d’entrée sur l’appareil continu, et vice versa.
Même dans les situations où le flux de continuation est requis, il doit y avoir un minimum de communication arrière et arrière entre les deux applications.
Pour plus d’informations, consultez la documentation d’Apple Using Continuation Flux.
Meilleures pratiques de transfert
L’implémentation réussie de la continuation transparente d’une activité utilisateur via handoff nécessite une conception minutieuse en raison de tous les différents composants impliqués. Apple suggère d’adopter les bonnes pratiques suivantes pour vos applications compatibles Handoff :
- Concevez vos activités utilisateur pour exiger la plus petite charge utile possible pour lier l’état de l’activité à poursuivre. Plus la charge utile est grande, plus la continuation est longue.
- Si vous devez transférer de grandes quantités de données pour une continuation réussie, prenez en compte les coûts liés à la configuration et à la surcharge réseau.
- Il est courant pour une grande application Mac de créer des activités utilisateur gérées par plusieurs applications spécifiques aux tâches plus petites sur les appareils iOS. Les différentes versions d’application et de système d’exploitation doivent être conçues pour fonctionner correctement ensemble ou échouer correctement.
- Lorsque vous spécifiez vos types d’activité, utilisez la notation DNS inversée pour éviter les collisions. Si une activité est spécifique à une application donnée, son nom doit être inclus dans la définition de type (par exemple
com.myCompany.myEditor.editing
). Si l’activité peut fonctionner sur plusieurs applications, supprimez le nom de l’application de la définition (par exemplecom.myCompany.editing
). - Si votre application doit mettre à jour l’état d’une activité utilisateur (
NSUserActivity
) définissez laNeedsSave
propriététrue
sur . À des moments appropriés, handoff appelle la méthode du délégué afin de pouvoir mettre à jour leUserInfo
dictionnaire en fonction desUserActivityWillSave
besoins. - Étant donné que le processus de transfert peut ne pas initialiser instantanément sur l’appareil de réception, vous devez implémenter les
AppDelegate
« sWillContinueUserActivity
» et informer l’utilisateur qu’une continuation est sur le point de commencer.
Exemple d’application de transfert
Un exemple d’utilisation de Handoff dans une application Xamarin.iOS est l’exemple d’application MonkeyBrowser . L’application comporte quatre onglets que l’utilisateur peut utiliser pour parcourir le web, chacun avec un type d’activité donné : Météo, Favoris, Pause café et Travail.
Sous n’importe quel onglet, lorsque l’utilisateur entre une nouvelle URL et appuie sur le bouton Go , un nouvel NSUserActivity
onglet est créé pour cet onglet qui contient l’URL que l’utilisateur navigue actuellement :
Si une autre des appareils de l’utilisateur a installé l’application MonkeyBrowser , est connectée à iCloud à l’aide du même compte d’utilisateur, se trouve sur le même réseau et à proximité de l’appareil ci-dessus, l’activité de transfert s’affiche sur l’écran d’accueil (dans le coin inférieur gauche) :
Si l’utilisateur fait glisser vers le haut sur l’icône De transfert, l’application est lancée et l’activité utilisateur spécifiée dans celle-ci NSUserActivity
est poursuivie sur le nouvel appareil :
Lorsque l’activité utilisateur a été correctement envoyée à un autre appareil Apple, l’appareil d’envoi NSUserActivity
reçoit un appel à la UserActivityWasContinued
méthode sur celui-ci NSUserActivityDelegate
pour lui indiquer que l’activité de l’utilisateur a été transférée avec succès vers un autre appareil.
Résumé
Cet article a donné une présentation de l’infrastructure Handoff utilisée pour poursuivre une activité utilisateur entre plusieurs appareils Apple de l’utilisateur. Ensuite, il a montré comment activer et implémenter handoff dans une application Xamarin.iOS. Enfin, il a abordé les différents types de continuations de transfert disponibles et les meilleures pratiques de transfert.