Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 

This is a little Proof of Concept project to demonstrate how easy it is to add a WatchKit extension to an OpenUI Agentry application. It shows how events and Agentry data can be shared with the WatchKit application to be displayed in the new device. Showing that business data is not "locked" inside the Agentry application and can be shared with users in many different ways.

The full source code for the project can be found here in SAP GitHub.

This is a GIF animation of the two applications working together:

For a higher resolution video, please contact me or access it in this JAM page. Enjoy!

Steps to create the App

Development starts with Xcode 6.2 and the OpenUI framework iOS Demo project.

The project was setup to add a WatchKit App and a WatchKit Extension following the instructions provided by Apple here.

Sharing data between the iOS App and the WatchKit App is achieved by setting up "App Groups". The instructions for doing so are described in this Apple article.

* Note: To test this, membership in an Apple Developer program is required because it will need to update the app entitlements and provisioning profiles.

Real time communication between the Watch App and the iOS App is achieved using the Darwin Notification Center and some new WatchKit APIs referenced in the documents mentioned above.

* Tip: There is an open source project available in GitHub here (MIT License) that encapsulates this paradigm rather elegantly. In this solution I manually implemented that because I wanted to see how it worked behind the scenes.


Communication from iPhone to Apple Watch

The sending happens in the MyCollectionDisplayAdapter.m file. See the updateSharedDataAndNotifyWatchKitExtension method. First, Agentry's object data is serialized into a helper object and stored in the App Group:

NSUserDefaults *sharedData = [[NSUserDefaults alloc]

    initWithSuiteName:@"group.com.syclo.agentry.SMPAgentryClientFrameworkDemo.shareddefaults"];


NSMutableArray* players = [NSMutableArray array];

for (int i = 0; i < self.model.displayedObjectCount; i++) {

 

  // Use DataAPI to get the value of the object's child properties

  id<SMPDataAPIProtocol> agentryPalyer = [self.model displayedObjectAtIndex:i];

  id<SMPDataAPIPropertyProtocol> nameProp = (id<SMPDataAPIPropertyProtocol>)[agentryPalyer descendant:0];

  // ...


  // Create the player

  Player* player = [[Player alloc] initWithName:[nameProp asString] ...;

  // Serialize it for saving

  [players addObject:[player serialize]];

}


[sharedData setObject:players forKey:@"players"];

[sharedData synchronize];


Then the notification is fired:

CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(),

  (__bridge CFStringRef)@"playersChanged",

  NULL,

  NULL,

  YES /* Deliver right now! */);

The receiving happens in the InterfaceController.m file of the WatchKit extension:

- (void) watchForDataChanges {

  // Listen for notifications on Darwing

  CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),

    (__bridge const void *)(self),

    darwinNotificationCenterCallBack,

    (__bridge CFStringRef)@"playersChanged",

    NULL,

    CFNotificationSuspensionBehaviorDeliverImmediately);


  // Listen for our own notification to ourselves in Cocoa

[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cocoaNotificationCallBack) name:@"playersChangedCocoa" object:nil];

}

 

void darwinNotificationCenterCallBack() {

  NSLog(@"Notification received from iPhone app!");

  // Go from Darwin to Cocoa land

  [[NSNotificationCenter defaultCenter] postNotificationName:@"playersChangedCocoa" object:nil];

}


- (void) cocoaNotificationCallBack {

  NSLog(@"Notification received from ourselves in Cocoa");

  [self loadTableData];

}


Note that some bridging from C to Obj-C is required to get the notification passed to the WatchKit UI code.


Also note, with this implementation, the OpenUI adapter code must be run at least once before there is any meaningful data in the Watch application to display.



Communication from Apple Watch back to iPhone


While the same method above works for two-way communication, there is another API the WatchKit API provides for communicating with the containing iPhone App.


For an example of this, check out this method in InterfaceController.m:


- (IBAction)doMenuAction {

  [WKInterfaceController openParentApplication:@{@"key" : @"value"}

    reply:

      ^(NSDictionary *replyInfo, NSError *error) {

        NSLog(@"Containing app returned!");

      }];

}


And in the AppDelegate provided with the iPhone Application.


- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {

  NSLog(@"Awoken by Apple WatchKit App!");


  UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Alert from   

    Watch!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

  [alert show];


  // ...

}


This same Watch application could be further extended to take advantage of the Notifications and Glances paradigms provided by Apple for its new wearable device.


Enjoy and share what you find playing with Agentry!

2 Comments