# How to: Handoff to a Xamarin iPhone app from Apple Watch
There are two ways to activate the parent (aka container) app from an Apple Watch app. You can either directly activate the container app using WKInterfaceController.OpenParentApplication
or you can use Handoff.
Using Handoff is a little more complex, so I thought I’d write a quick little how-to. There are a few different Handoff scenarios, but perhaps the most common for the Watch is: “On my watch I want to begin a task that I complete later on my iPhone.” So, for instance, some task that requires either more data-entry than is appropriate for the watch or some capabilities not available on the watch.
I want to keep the focus on the APIs, so instead of a real-world sample, I’m going to create a minimal example: a button on the Watch activates handoff and a status label on the phone app is updated when the user activity is continued on the phone.
As always, we have a single Solution with 3 projects: the parent App, the Watch extension, and the Watch App.
Every handoff activity has a unique identifier. By convention, this is a domain-reversed string such as: com.xamarin.HandOffDemo.verb
.
To trigger the Handoff behavior, the watch extension calls the WKInterfaceController.UpdateUserActivity
method, with its first argument set equal to this identifier:
[code lang="csharp"]
partial void ActivateHandoffClicked (WatchKit.WKInterfaceButton sender)
{
var userInfo = NSDictionary.FromObjectAndKey(new NSString(“value”), new NSString(“key”));
this.UpdateUserActivity(“com.xamarin.HandOffDemo.verb”, userInfo, null);
}
[/code]
The third argument is a NSUrl
object that can be used for Handoff tasks that should be handled by Safari. But in our case, we’re handing the userInfo
dictionary containing the very complex data associated with our handoff.
Your parent app registers its interest in this type of handoff within its info.plist
. In the parent app info.plist
, add a new array called NSUserActivityTypes
and add to it a string with value com.xamarin.HandOffDemo.verb
It’s possible that an app could be interested in certain handoffs, but not always be in a position to actually handle them. That logic can be placed in an override of the UIApplicationDelegate.WillContinueUserActivity
method:
[code lang="csharp"]
public override bool WillContinueUserActivity (UIApplication application, string userActivityType)
{
//Yeah, we can handle it
return true;
}
[/code]
Assuming that we return true
from that method, the next step is to override the UIApplicationDelegate.ContinueUserActivity
method:
An architectural issue that needs to be addressed is that this Handoff re-entry point is in the UIApplicationDelegate
object, which of course does not have an associated user interface. There are several ways to handle this, but as a fan of reactive programming, I think the proper design is to create either an IObservable
sequence or a more traditional C# event, which is what I do here:
[code lang="csharp"]
public event EventHandler HandoffOccurred = delegate {};
public override bool ContinueUserActivity (UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
HandoffOccurred?.Invoke (this, userActivity.UserInfo);
return true;
}
[/code]
The third parameter, completionHandler
used if you have references to custom UIResponder
objects that should handle the user activity. In the case, you put those references in a NSArray
and pass them to completionHandler
, which will cause each of their ContinueUserActivity
methods to be called. (Update: Apple would probably prefer this technique to my event, but I am not sure if it's necessary, and it requires the UIApplicationDelegate
to maintain a reference to the subscribing UIResponder
, so you either have an ugly dependency or you have to implement some kind of Observer / Subscriber pattern. So I still would suggest an event or IObservable
as the better solution.)
In the parent app’s main UIViewController
class, I have:
[code lang="csharp"]
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
//Configure user experience for Handoff
var myAppDel = (AppDelegate) UIApplication.SharedApplication.Delegate;
myAppDel.HandoffOccurred += HandoffOccurred;
}
public void HandoffOccurred(object sender, NSDictionary userInfo)
{
InvokeOnMainThread( () => statusLabel.Text = userInfo[“key”].ToString() );
}
[/code]
And that’s all there is to it. Obviously, a real use-case would involve building a more complex NSDictionary
holding the context of the watch interaction and a similarly complex handler in the parent app.
Now, when the Handoff is activated from the Apple Watch, my iPhone lock screen shows the icon of the parent app in the lower-left corner. If I drag that up, the parent app opens, the re-entry process begins, with UIApplicationDelegate.WillContinueUserActivity
and UIApplicationDelegate.ContinueUserActivity
.
https://www.youtube.com/watch?v=XKt-7EVfEDs