/appc-sample-notifywatch

Supporting Apple Watch without the Kit.

Primary LanguageJavaScriptOtherNOASSERTION

Interactive Notifications for iOS and Apple Watch

Or... Supporting Apple Watch without the Kit/OS2.

Titanium & Apple Watch

Titanium 4.1 already supports linking a WatchKit Extension built in Xcode, and our upcoming September 2015 release adds support for linking and communicating with Watch OS 2 apps built using Swift. Of course we are also working on the ability to build an actual Watch OS 2 app in JavaScript using Titanium. But today I will show how you can support the Apple Watch without any of that using Titanium 3.4.0 or later.

Interactive Notifications

What I personally use most on the Apple Watch are interactive notifications. Third party apps often are painfully slow, although I assume that will improve once they are able to run on the watch with Watch OS 2.

Interactive notifications have been available for phone and tablet since iOS 8 and Titanium 3.4.0, but proved to be even more useful on the Watch. Getting a notification about an incoming message is fine, but if I don't have to grab my phone to reply we are really talking — literally! I'd still rather use my phone instead of having to type or dictate on my watch, but interactive notifications are great for selecting a quick reply or actions like Mark as Read.

Sample App

I've built a sample messenger app to show you how it works. It's a simple WhatsApp-like messaging app. Every time you send a message, a pretty dumb bot will reply with a random answer after 4 seconds. This allows you to move the app to the background or lock your phone to see what happens in different scenarios.

The repository includes screenshots of different types of interactive notifications.

screenshots

NOTE: As you can see, action titles can contain emojis — yeah!

Architecture

I tried to keep the app as simple as possible.

NOTE: There is a known issue that the ListView sometimes will not render. Simply restart the app when this occurs. The issue is fixed for the next minor SDK release.

Setting up interactive notifications

Interactive notifications can be scheduled locally by the app itself or pushed.

In both cases we first have to set up the interactive notification categories and actions. We do this in the first ~150 lines of app/lib/notifications.js.

Since iOS 8 you need to use Ti.App.iOS.registerUserNotificationSettings to set the notification types (alert, badge, sound) for both local and push. We use the same method to set the categories which in turn hold the interactive actions.

Registering categories

A category may define two sets of actions. One of 1-4 actions for alert-style and Apple Watch notifications and another of 1-2 actions for other styles. If you don't set the latter it will simply take the first two of the first.

NOTE: Apple Watch will only display actions that can be processed in the background.

Registering actions

Apart from an identifier and title there's a few things you can set:

  • activationMode: If set to Ti.App.iOS.USER_NOTIFICATION_ACTIVATION_MODE_BACKGROUND it will just let the app execute the action without opening the app for the user.
  • authenticationRequired: If set to true and only when the user is not selecting the action via his watch, he must authenticate first, even if the device is not locked.
  • destructive: Will display the action in red if presented on the lock screen or watch.

NOTE: Using authenticationRequired:false and activationMode:Ti.App.iOS.USER_NOTIFICATION_ACTIVATION_MODE_FOREGROUND together will still require authentication if the device is locked.

Receiving local notifications

From line ~160 we listen for local notifications.

The notification event is fired for both regular and interactive notifications when the app is opened via a local notification, but only when the user has not selected an action. It also fires when the app was in the foreground while receiving the notification. There's no way to tell the difference, but in both cases we want to present the message to the user so he can respond to it in the app.

NOTE: When the app is in foreground iOS will never show the notification to the user. It expects the app to handle it.

A separate localnotificationaction event is fired when the user does select an action. It will have the notification payload as well as the category and selected action identifiers. You can see how we handle this around line ~190. Since we have push notifications as well, I choose to use an event dispatcher created in alloy.js and trigger a custom action event with the required payload. I'll listen to this event in the console and chat controllers.

Receiving push notifications

The sample app is prepared to receive interactive push notifications in lines 209+, but you will need to create an ArrowDB datasource and add your key in tiapp.xml for it to work.

When the user has responded to a push notification by selecting an action, the remotenotificationaction will be fired. We handle this in the same way as we did for local notifications.

Sending interactive notifications

Local notifications

The chat uses local notifications and the console tab has a button to send one as well. In app/controllers/console.js you can see how we use Ti.App.iOS.scheduleLocalNotification.

  • alertAction: Should be a verb plus optional subject since it will used instead of the default Open for alert-style notifications and in Slide to [alertAction] on the lock screen.
  • date: Optional date to schedule for or leave it out to send it now.
  • category: If set, it must be the identifier for one of the interactive notification categories we registered.
  • userInfo: Can be any object. Our sample uses it to pass the ID of the message which we need to handle the action.

Push notifications

To send an interactive push notification, use the Dashboard or API and including a valid category value and optional payload.

screenshot

The chat

I won't go into too much detail on how the chat works, but here's what app/controllers/chat.js does:

See the comments throughout the code for more details.

Update: Text Input

With Titanium 5.1 we've introduced the behavior property for actions. With just a few modifications in lib/notifications.js en the chat controller you can now reply with a custom message directly from the notification banner or by dictating it to your Apple Watch:

choice

Bonus: Handoff

As a bonus, viewing a notification on your Watch automatically triggers handoff for the Titanium app. Your app icon will show in the bottom left of the lock screen and swiping up will open the app. However, consecutive tests using the sample didn't always get the same results for me and only in Titanium 5.0 and later will you be able to listen to the handoff event in your app.

screenshot

Links