Announcing Project Rome iOS SDK

Project Rome is a platform for enabling seamless cross-device and cross-platform experiences. The philosophy behind Project Rome is simple. App experiences shouldn’t be tied to a single device any more than data should be tied to a single device. Your apps, like your data, should travel with you.

Previously, this meant switching between devices, while maintaining a single user experience, on a different Windows device. A few months ago, Project Rome features were extended to the Android platform, allowing you to start an app session on your Android phone and continue it on a Windows PC, an Xbox One or even a Surface Hub.

Now, Project Rome support is also being extended to the iOS platform. You can download the Project Rome SDK for iOS here.

Revisiting the Contoso music app

If you have been following the evolution of Project Rome, you’ll be familiar with our developer friend Paul and his example Contoso Music app. Paul was originally introduced in a blog post on Cross-device experiences to help us understand a typical Project Rome scenario.

He expanded his UWP music streaming app to run across multiple Windows devices tied to the same Microsoft Account (MSA). Using Project Rome, Paul changed how his app worked so a user streaming a song on a Windows PC could then transfer that song to his Xbox. Then, as he got ready to go out for a run, he could transfer the current playlist to his Windows Phone.

In the subsequent post, Paul developed an Android version of Contoso Music app and used the Project Rome Android SDK to allow a user to start playing a song on her Android phone and continue playing it on a Windows device when he or she got home. The Contoso Music app was now cross-platform, transferring smoothly from one platform to the next.

Extending to iOS

Let’s imagine that based on the success of his Windows and Android versions, Paul develops an iOS version of Contoso Music. When examining his telemetry after a few months, Paul sees that all his apps are doing well, like his Windows and Android versions. However, there is a common theme in the user feedback; users are finding it difficult handling device switching. So, Paul wants to enable a scenario in which a user can listen to music on the iPhone over headphones, then enter the living room and immediately switch to playing the same music over his Xbox, connected to quality speakers.

With the Project Rome iOS SDK, Paul can create a bridge between iOS devices and Windows devices in two stages:

  • The RemoteSystems API allows the app to discover Windows devices the user owns. The RemoteSystems API will allow the Contoso Music app to discover these devices on the same network or through the cloud.
  • Once discovered, the RemoteLauncher API will launch the Contoso Music app on another Windows device.

How Paul gets it done

In order for Paul’s user to switch from playing music on an iOS device to a Windows device, his app must find out about the other device. This action requires using MSA OAuth to get permission to query for devices and then attempting to discover additional devices, as shown in the diagram below.



// Asynchronously initialize the Rome Platform.
  // Pass in self as class implements the CDOAuthCodeProviderDelegate protocol.
  [CDPlatform startWithOAuthCodeProviderDelegate:self completion:^(NSError* clientError) {
                                              if (clientError)
                                              {
                                                  // Handle error
                                                  return;
                                              }

                                              // Handle success, show discovery screen
                                      }];

// Implementation of CDOAuthCodeProviderDelegate
// The Rome SDK calls this delegate method when it needs an OAuth Access Code from the application.
- (NSError*)getAccessCode:(NSString*)signinUrl completion: (void (^)(NSError* error, NSString* accessCode))completion {

// Stash away the callback the SDK gives us
_getTokenCallback = completion;

  // Show the interactive OAuth Web View flow.
  // Once the OAuth flow completes or fails, invoke this callback.
  ...

// Return nil as there was no error
  return nil;
}


Once initialized, Paul’s app can discover all devices in the user’s MSA device graph by initiating discovery using CDRemoteSystemDiscoveryManager. Information about discovered devices are raised through the CDRemoteSystemDiscoveryManagerDelegate protocol. In In our example, we store each discovered device within an NSMutableArray property called discoveredSystems.



// Create instance and pass ‘self’ as the delegate as it implements CDRemoteSystemDiscoveryManagerDelegate.
CDRemoteSystemDiscoveryManager* remoteSystemDiscoveryManager = [[CDRemoteSystemDiscoveryManager alloc] initWithDelegate:self];

// Start discovery.
[remoteSystemDiscoveryManager startDiscovery];

// CDRemoteSystemDiscoveryManagerDelegate implementation
- (void)remoteSystemDiscoveryManager:
            (CDRemoteSystemDiscoveryManager*)discoveryManager
                             didFind:(CDRemoteSystem*)remoteSystem {
  @synchronized(self) {
     [self.discoveredSystems addObject:remoteSystem];
      // Refresh UI based upon updated state in discoveredSystems e.g. populate table
   }
}

- (void)remoteSystemDiscoveryManager:
            (CDRemoteSystemDiscoveryManager*)discoveryManager
                           didUpdate:(CDRemoteSystem*)remoteSystem {
  NSString* id = remoteSystem.id;

// Loop through and update the Remote System instance if previously seen.
  @synchronized(self) {
    for (unsigned i = 0; i < self.discoveredSystems.count; i++) {
      CDRemoteSystem* currentRemoteSystem =
          [self.discoveredSystems objectAtIndex:i];
      NSString* currentId = currentRemoteSystem.id;

      if ([currentId isEqualToString:id]) {
        [self.discoveredSystems replaceObjectAtIndex:i withObject:remoteSystem];
        break;
      }
    }

       // Refresh UI based upon updated state in discoveredSystems e.g. populate table
  }
}


The user can now select the device he wants to transfer music to from the list of devices that have been discovered. From the selected CDRemoteSystem, an instance of CDRemoteSystemConnectionRequest is instantiated as shown in the sequence diagram below. Using CDRemoteLauncher, Paul is then able to remotely launch the app on the selected device while also including necessary additional contextual information, such as the song currently playing.

Here’s how to remote-launch http://www.bing.com to your device:



// Create a connection request using the CDRemoteSystem instance selected by the user
  CDRemoteSystemConnectionRequest* request =
       // Using the RemoteSystem above, [self.discoveredSystems addObject:remoteSystem];
      [[CDRemoteSystemConnectionRequest alloc] initWithRemoteSystem:system];

NSString* url = @”http://www.bing.com”;

  [CDRemoteLauncher
           launchUri:uri
           withRequest:request
           withCompletion:^(CDRemoteLauncherUriStatus status) {
            // Update UI on launch status
            }];


Voila! Paul has easily augmented his app with cross-device support for iOS.

Wrapping up

Project Rome breaks down barriers by changing notions about what an “app” is and focusing on the user no matter where they are working or what device they are using. An app no longer necessarily means something that is tied to a given device, instead it can be something that exists between your devices and is optimized for the right device at the right time. Today, Project Rome works on Windows 10, Android and iOS. Stay tuned to see what comes next.

To learn more about Project Rome, check out the links below.