OneSignal / OneSignal-iOS-SDK

OneSignal is a free push notification service for mobile apps. This plugin makes it easy to integrate your native iOS app with OneSignal. https://onesignal.com
Other
496 stars 263 forks source link

Push to start live activities #1377

Closed brismithers closed 6 months ago

brismithers commented 8 months ago

Description

One Line Summary

Update SDK to support Live Activities PushToStart and add a concept of a "Default" Live Activity to facilitate easier wrapper SDK adoption.

Details

Push to Start Live Activities

Starting with iOS 17.2, Live Activities can now be started via push notification (Apple's documentation). This change enhances the OneSignal SDK to provide application's access to the full suite of Live Activity functionality.

Preferred method to setup Live Activities with OneSignal

A new function OneSignal.LiveActivities.setup has been created which allows OneSignal to manage the lifecycle of a LiveActivity on behalf of the application. This includes listening for both pushToStart token updates and pushToUpdate token updates. When using this method, the application does not need to listen for pushToStart token updates, the starting of a live activity, nor update token updates. A typical usage looks like this:

OneSignal.LiveActivities.setup(MyWidgetAttributes.self)

This method accepts any struct which adopts the OneSignalLiveActivityAttributes protocol. The OneSignalLiveActivityAttributes protocol establishes a high-level onesignal attribute and a high-level onesignal content state property which will be used internally by OneSignal. At a minimum, your attributes will have the following structure:

 struct MyWidgetAttributes: OneSignalLiveActivityAttributes {
     public struct ContentState: OneSignalLiveActivityContentState {
         // Your content state properties defined here as well...

         // A content state property reserved for OneSignal internal use.
         var onesignal: OneSignalLiveActivityContentStateData?
     }

     // Your attribute properties defined here as well...

     // An attribute property reserved for OneSignal internal use.
     var onesignal: OneSignalLiveActivityAttributeData
 }

If an application starts a live activity "in app" it no longer has to listen for token updates explicitly, starting a Live Activity "in-app" will look something like this:

 let oneSignalAttribute = OneSignalLiveActivityAttributeData.create(activityId: "my-activity-id")
 let attributes = MyWidgetAttributes(onesignal: oneSignalAttribute, ...otherWidgetAttributes)
 let contentState = MyWidgetAttributes.ContentState(widgetContentState)
 do {
     let _ = try Activity<MyWidgetAttributes>.request(
             attributes: attributes,
             contentState: contentState,
             pushType: .token)
 } catch let error {
     print(error.localizedDescription)
 }

Alternative (low level) method to setup Live Activities with OneSignal

If a customer app does not want to alter their ActivityAttribute structure, or wants more fine grained control over when OneSignal should manage a Live Activity's start/update tokens, lower-level SDK methods are provided. These methods require the application to listen for pushToStart token updates, the starting of live activities, and update token updates. This encompasses existing
functions OneSignal.LiveActivities.enter and OneSignal.LiveActivities.exit which are documented here. Additional new methods to cover registering/unregistering pushToStart tokens have been created:

if #available(iOS 17.2, *) {
  // Setup an async task to monitor and send pushToStartToken updates to OneSignalSDK.
  Task {
      for try await data in Activity<MyWidgetAttributes>.pushToStartTokenUpdates {
          let token = data.map {String(format: "%02x", $0)}.joined()
          OneSignal.LiveActivities.setPushToStartToken(MyWidgetAttributes.self, withToken: token)
      }
  }
  // Setup an async task to monitor for an activity to be started, for each started activity we
  // can then set up an async task to monitor and send updateToken updates to OneSignalSDK. If
  // there can be multiple instances of this activity-type, the activity-id (i.e. "my-activity-id") is
  // most likely passed down as an attribute within MyWidgetAttributes.
  Task {
      for await activity in Activity<MyWidgetAttributes>.activityUpdates {
        Task {
            for await pushToken in activity.pushTokenUpdates {
                let token = pushToken.map {String(format: "%02x", $0)}.joined()
                OneSignal.LiveActivities.enter("my-activity-id", withToken: token)
            }
        }
      }
  }
}
OneSignal.LiveActivities.removePushToStartToken(MyWidgetAttributes.self)

Default Live Activity

The concept of a "Default" Live Activity has been established in the SDK, which eliminates the need for a customer app to define and manage their own ActivityAttributes. This is most beneficial for wrapper-SDKs, as they will no longer need to create their own cross-platform <-> native iOS bridge to establish this management. The following new external interfaces are provided for customer app's to use:

The downside to using a default Live Activity is:

Motivation

Full support of Live Activities functionality introduced in iOS 17.2

Scope

Live Activities

Testing

Unit testing

Manual testing

Affected code checklist

Checklist

Overview

Testing

Final pass


This change is Reviewable