diff --git a/pushy/src/main/java/com/eatthepath/pushy/apns/util/ApnsPayloadBuilder.java b/pushy/src/main/java/com/eatthepath/pushy/apns/util/ApnsPayloadBuilder.java index b2534dafa..7b4083e55 100644 --- a/pushy/src/main/java/com/eatthepath/pushy/apns/util/ApnsPayloadBuilder.java +++ b/pushy/src/main/java/com/eatthepath/pushy/apns/util/ApnsPayloadBuilder.java @@ -89,6 +89,9 @@ public abstract class ApnsPayloadBuilder { private Instant staleDate = null; + private String attributesType = null; + private Map attributes = null; + private Map contentState = null; private static final String APS_KEY = "aps"; @@ -125,6 +128,8 @@ public abstract class ApnsPayloadBuilder { private static final String DISMISSAL_DATE_KEY = "dismissal-date"; private static final String STALE_DATE_KEY = "stale-date"; private static final String EVENT_KEY = "event"; + private static final String ATTRIBUTES_TYPE_KEY = "attributes-type"; + private static final String ATTRIBUTES_KEY = "attributes"; private static final String CONTENT_STATE_KEY = "content-state"; public static final String[] EMPTY_STRING_ARRAY = new String[0]; @@ -756,6 +761,46 @@ public ApnsPayloadBuilder addCustomProperty(final String key, final Object value return this; } + /** + * Sets the type of iOS {@code ActivityAttributes} used for a Live Activity. Must be set for a notification that + * starts a live activity. + * + * @param attributesType the type of {@code ActivityAttributes} used for a Live Activity + * + * @return a reference to this payload builder + * + * @see #setAttributes(Map) + * @see + * Construct the payload that starts a Live Activity + * @see ActivityKit - ActivityAttributes + * + * @since 0.15.4 + */ + public ApnsPayloadBuilder setAttributesType(final String attributesType) { + this.attributesType = attributesType; + return this; + } + + /** + * Sets the values of iOS {@code ContentState} attributes when starting a Live Activity. Must be set for a + * notification that starts a live activity. + * + * @param attributes the attributes used to populate the {@code ContentState} for the newly-started live activity + * + * @return a reference to this payload builder + * + * @see #setAttributesType(String) + * @see + * Construct the payload that starts a Live Activity + * @see ActivityKit - ContentState + * + * @since 0.15.4 + */ + public ApnsPayloadBuilder setAttributes(final Map attributes) { + this.attributes = attributes; + return this; + } + /** *

Sets the content state object inside content-state payload for Live Activities.

* @@ -768,6 +813,8 @@ public ApnsPayloadBuilder addCustomProperty(final String key, final Object value * * @see * Updating and ending your Live Activity with remote push notifications + * + * @since 0.15.2 */ public ApnsPayloadBuilder setContentState(final Map contentState) { this.contentState = contentState; @@ -784,6 +831,8 @@ public ApnsPayloadBuilder setContentState(final Map contentState * * @see * Updating and ending your Live Activity with remote push notifications + * + * @since 0.15.2 */ public ApnsPayloadBuilder setEvent(final LiveActivityEvent event) { this.event = event; @@ -799,6 +848,8 @@ public ApnsPayloadBuilder setEvent(final LiveActivityEvent event) { * * @see * Updating and ending your Live Activity with remote push notifications + * + * @since 0.15.2 */ public ApnsPayloadBuilder setTimestamp(final Instant timestamp) { this.timestamp = timestamp; @@ -819,6 +870,8 @@ public ApnsPayloadBuilder setTimestamp(final Instant timestamp) { * * @see * Updating and ending your Live Activity with remote push notifications + * + * @since 0.15.2 */ public ApnsPayloadBuilder setDismissalDate(final Instant dismissalDate) { this.dismissalDate = dismissalDate; @@ -891,6 +944,14 @@ protected Map buildPayloadMap() { aps.put(EVENT_KEY, this.event.getValue()); } + if (this.attributesType != null) { + aps.put(ATTRIBUTES_TYPE_KEY, this.attributesType); + } + + if (this.attributes != null) { + aps.put(ATTRIBUTES_KEY, this.attributes); + } + if (this.contentState != null) { aps.put(CONTENT_STATE_KEY, this.contentState); } diff --git a/pushy/src/test/java/com/eatthepath/pushy/apns/util/ApnsPayloadBuilderTest.java b/pushy/src/test/java/com/eatthepath/pushy/apns/util/ApnsPayloadBuilderTest.java index 21c06dec6..ff9a4815e 100644 --- a/pushy/src/test/java/com/eatthepath/pushy/apns/util/ApnsPayloadBuilderTest.java +++ b/pushy/src/test/java/com/eatthepath/pushy/apns/util/ApnsPayloadBuilderTest.java @@ -29,7 +29,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.ValueSource; import java.text.ParseException; import java.time.Instant; @@ -665,6 +664,42 @@ void setEvent(LiveActivityEvent event) { assertEquals(event.getValue(), aps.get("event")); } + @Test + void testSetAttributesType() { + final String attributesType = "TestAttributes"; + this.builder.setAttributesType(attributesType); + + final Map aps = this.extractApsObjectFromPayloadString(this.builder.build()); + + assertEquals(attributesType, aps.get("attributes-type")); + } + + @Test + void testSetAttributes() { + final String keyForStringValue = "string"; + final String stringValue = "Hello"; + + final String keyForLongValue = "integer"; + final long longValue = 12; + + final String keyForMapValue = "map"; + final Map attributes = new HashMap<>(); + final Map subMap = new HashMap<>(); + subMap.put("boolean", true); + attributes.put(keyForLongValue, longValue); + attributes.put(keyForStringValue, stringValue); + attributes.put(keyForMapValue, subMap); + + this.builder.setAttributes(attributes); + + final Map aps = this.extractApsObjectFromPayloadString(this.builder.build()); + final Map serializedAttributes = (Map) aps.get("attributes"); + + assertEquals(stringValue, serializedAttributes.get(keyForStringValue)); + assertEquals(longValue, serializedAttributes.get(keyForLongValue)); + assertEquals(subMap, serializedAttributes.get(keyForMapValue)); + } + @Test void testAddContentStateProperty() { final String keyForStringValue = "string";