Skip to content

Commit

Permalink
Added support for localized subtitles.
Browse files Browse the repository at this point in the history
  • Loading branch information
jchambers committed Sep 8, 2016
1 parent 9decce1 commit aba34ee
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ public class ApnsPayloadBuilder {
private String localizedAlertKey = null;
private String[] localizedAlertArguments = null;
private String alertTitle = null;
private String alertSubtitle = null;
private String localizedAlertTitleKey = null;
private String[] localizedAlertTitleArguments = null;
private String alertSubtitle = null;
private String localizedAlertSubtitleKey = null;
private String[] localizedAlertSubtitleArguments = null;
private String launchImageFileName = null;
private boolean showActionButton = true;
private String localizedActionButtonKey = null;
Expand All @@ -68,13 +70,15 @@ public class ApnsPayloadBuilder {
private static final String MUTABLE_CONTENT_KEY = "mutable-content";

private static final String ALERT_TITLE_KEY = "title";
private static final String ALERT_SUBTITLE_KEY = "subtitle";
private static final String ALERT_BODY_KEY = "body";
private static final String ALERT_TITLE_LOC_KEY = "title-loc-key";
private static final String ALERT_TITLE_ARGS_KEY = "title-loc-args";
private static final String ACTION_LOC_KEY = "action-loc-key";
private static final String ALERT_SUBTITLE_KEY = "subtitle";
private static final String ALERT_SUBTITLE_LOC_KEY = "subtitle-loc-key";
private static final String ALERT_SUBTITLE_ARGS_KEY = "subtitle-loc-args";
private static final String ALERT_BODY_KEY = "body";
private static final String ALERT_LOC_KEY = "loc-key";
private static final String ALERT_ARGS_KEY = "loc-args";
private static final String ACTION_LOC_KEY = "action-loc-key";
private static final String LAUNCH_IMAGE_KEY = "launch-image";

private final HashMap<String, Object> customProperties = new HashMap<String, Object>();
Expand Down Expand Up @@ -176,18 +180,6 @@ public ApnsPayloadBuilder setAlertTitle(final String alertTitle) {
return this;
}

/**
* Sets a subtitle for the notification. Requires iOS 10 or newer.
*
* @param alertSubtitle the subtitle for this push notification
*
* @return a reference to this payload builder
*/
public ApnsPayloadBuilder setAlertSubtitle(final String alertSubtitle) {
this.alertSubtitle = alertSubtitle;
return this;
}

/**
* <p>Sets the key of the title string in the receiving app's localized string list to be shown for the push
* notification. The message in the app's string list may optionally have placeholders, which will be populated by
Expand Down Expand Up @@ -216,6 +208,53 @@ public ApnsPayloadBuilder setLocalizedAlertTitle(final String localizedAlertTitl
return this;
}

/**
* Sets a subtitle for the notification. Requires iOS 10 or newer.
*
* @param alertSubtitle the subtitle for this push notification
*
* @return a reference to this payload builder
*
* @since 0.8.1
*/
public ApnsPayloadBuilder setAlertSubtitle(final String alertSubtitle) {
if (alertSubtitle != null && this.localizedAlertSubtitleKey != null) {
throw new IllegalStateException("Cannot set a literal subtitle when a localized subtitle key has already been set");
}

this.alertSubtitle = alertSubtitle;

return this;
}

/**
* <p>Sets the key of the subtitle string in the receiving app's localized string list to be shown for the push
* notification. The message in the app's string list may optionally have placeholders, which will be populated by
* values from the given {@code alertSubtitleArguments}.</p>
*
* @param localizedAlertSubtitleKey a key to a string in the receiving app's localized string list
* @param alertSubtitleArguments arguments to populate placeholders in the localized subtitle string; may be
* {@code null}
*
* @return a reference to this payload builder
*
* @since 0.8.1
*/
public ApnsPayloadBuilder setLocalizedAlertSubtitle(final String localizedAlertSubtitleKey, final String... alertSubtitleArguments) {
if (localizedAlertSubtitleKey != null && this.alertSubtitle != null) {
throw new IllegalStateException("Cannot set a localized subtitle key when a literal subtitle has already been set");
}

if (localizedAlertSubtitleKey == null && alertSubtitleArguments != null) {
throw new IllegalArgumentException("Cannot set localized subtitle arguments without a localized subtitle key.");
}

this.localizedAlertSubtitleKey = localizedAlertSubtitleKey;
this.localizedAlertSubtitleArguments = alertSubtitleArguments;

return this;
}

/**
* <p>Sets the image to be shown when the receiving app launches in response to this push notification. According
* to Apple's documentation, this should be:</p>
Expand Down Expand Up @@ -553,6 +592,14 @@ private Object createAlertObject() {
}
}

if (this.localizedAlertSubtitleKey != null) {
alert.put(ALERT_SUBTITLE_LOC_KEY, this.localizedAlertSubtitleKey);

if (this.localizedAlertSubtitleArguments != null) {
alert.put(ALERT_SUBTITLE_ARGS_KEY, Arrays.asList(this.localizedAlertSubtitleArguments));
}
}

if (this.launchImageFileName != null) {
alert.put(LAUNCH_IMAGE_KEY, this.launchImageFileName);
}
Expand All @@ -572,7 +619,8 @@ private Object createAlertObject() {
private boolean hasAlertContent() {
return this.alertBody != null || this.alertTitle != null || this.localizedAlertTitleKey != null
|| this.localizedAlertKey != null || this.localizedActionButtonKey != null
|| this.launchImageFileName != null || this.showActionButton == false || this.alertSubtitle != null;
|| this.launchImageFileName != null || this.showActionButton == false || this.alertSubtitle != null
|| this.localizedAlertSubtitleKey != null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,108 +76,152 @@ public void testSetAlertBody() {
}
}

@SuppressWarnings("unchecked")
@Test
public void testSetAlertTitle() {
final String alertTitle = "This is a test alert message.";

this.builder.setAlertTitle(alertTitle);
public void testSetLocalizedAlertBody() {
final String alertKey = "test.alert";
this.builder.setLocalizedAlertMessage(alertKey, null);

{
final Map<String, Object> aps = this.extractApsObjectFromPayloadString(this.builder.buildWithDefaultMaximumLength());
final Map<String, Object> alert = (Map<String, Object>) aps.get("alert");

@SuppressWarnings("unchecked")
assertEquals(alertKey, alert.get("loc-key"));
assertNull(alert.get("loc-args"));
}

final String[] alertArgs = new String[] { "Moose", "helicopter" };
this.builder.setLocalizedAlertMessage(alertKey, alertArgs);

{
final Map<String, Object> aps = this.extractApsObjectFromPayloadString(this.builder.buildWithDefaultMaximumLength());
final Map<String, Object> alert = (Map<String, Object>) aps.get("alert");

assertEquals(alertTitle, alert.get("title"));
assertEquals(alertKey, alert.get("loc-key"));

final List<Object> argsArray = (List<Object>) alert.get("loc-args");
assertEquals(alertArgs.length, argsArray.size());
assertTrue(argsArray.containsAll(java.util.Arrays.asList(alertArgs)));
}
}

@Test(expected = IllegalStateException.class)
public void testSetAlertBodyWithExistingLocalizedAlert() {
this.builder.setLocalizedAlertMessage("Test", null);
this.builder.setAlertBody("Test");
}

@Test(expected = IllegalStateException.class)
public void testSetLocalizedAlertWithExistingAlertBody() {
this.builder.setAlertBody("Test");
this.builder.setLocalizedAlertMessage("Test", null);
}

@Test
public void testSetAlertSubTitle() {
final String alertSubtitle = "This is a test alert message.";
public void testSetAlertTitle() {
final String alertTitle = "This is a test alert message.";

this.builder.setAlertSubtitle(alertSubtitle);
this.builder.setAlertTitle(alertTitle);

{
final Map<String, Object> aps = this.extractApsObjectFromPayloadString(this.builder.buildWithDefaultMaximumLength());

@SuppressWarnings("unchecked")
final Map<String, Object> alert = (Map<String, Object>) aps.get("alert");

assertEquals(alertSubtitle, alert.get("subtitle"));
assertEquals(alertTitle, alert.get("title"));
}
}

@Test
public void testSetAlertTitleAndBody() {
final String alertTitle = "This is a short alert title";
final String alertBody = "This is a longer alert body";
public void testSetLocalizedAlertTitle() {
final String localizedAlertTitleKey = "alert.title";

this.builder.setAlertBody(alertBody);
this.builder.setAlertTitle(alertTitle);
this.builder.setLocalizedAlertTitle(localizedAlertTitleKey, null);

{
final Map<String, Object> aps = this.extractApsObjectFromPayloadString(this.builder.buildWithDefaultMaximumLength());

@SuppressWarnings("unchecked")
final Map<String, Object> alert = (Map<String, Object>) aps.get("alert");

assertEquals(alertTitle, alert.get("title"));
assertEquals(alertBody, alert.get("body"));
assertEquals(localizedAlertTitleKey, alert.get("title-loc-key"));
}
}

@SuppressWarnings("unchecked")
@Test(expected = IllegalStateException.class)
public void testSetAlertTitleWithExistingLocalizedAlertTitle() {
this.builder.setLocalizedAlertTitle("Test", null);
this.builder.setAlertTitle("Test");
}

@Test(expected = IllegalStateException.class)
public void testSetLocalizedAlertTitleWithExistingAlertTitle() {
this.builder.setAlertTitle("Test");
this.builder.setLocalizedAlertTitle("Test", null);
}

@Test
public void testSetLocalizedAlertMessage() {
final String alertKey = "test.alert";
this.builder.setLocalizedAlertMessage(alertKey, null);
public void testSetAlertSubtitle() {
final String alertSubtitle = "This is a test alert message.";

this.builder.setAlertSubtitle(alertSubtitle);

{
final Map<String, Object> aps = this.extractApsObjectFromPayloadString(this.builder.buildWithDefaultMaximumLength());

@SuppressWarnings("unchecked")
final Map<String, Object> alert = (Map<String, Object>) aps.get("alert");

assertEquals(alertKey, alert.get("loc-key"));
assertNull(alert.get("loc-args"));
assertEquals(alertSubtitle, alert.get("subtitle"));
}
}

final String[] alertArgs = new String[] { "Moose", "helicopter" };
this.builder.setLocalizedAlertMessage(alertKey, alertArgs);
@Test
public void testSetLocalizedAlertSubitle() {
final String localizedAlertSubtitleKey = "alert.subtitle";

this.builder.setLocalizedAlertSubtitle(localizedAlertSubtitleKey);

{
final Map<String, Object> aps = this.extractApsObjectFromPayloadString(this.builder.buildWithDefaultMaximumLength());
final Map<String, Object> alert = (Map<String, Object>) aps.get("alert");

assertEquals(alertKey, alert.get("loc-key"));
@SuppressWarnings("unchecked")
final Map<String, Object> alert = (Map<String, Object>) aps.get("alert");

final List<Object> argsArray = (List<Object>) alert.get("loc-args");
assertEquals(alertArgs.length, argsArray.size());
assertTrue(argsArray.containsAll(java.util.Arrays.asList(alertArgs)));
assertEquals(localizedAlertSubtitleKey, alert.get("subtitle-loc-key"));
}
}

@Test(expected = IllegalStateException.class)
public void testSetAlertBodyWithExistingLocalizedAlert() {
this.builder.setLocalizedAlertMessage("Test", null);
this.builder.setAlertBody("Test");
public void testSetAlertSubtitleWithExistingLocalizedAlertSubtitle() {
this.builder.setLocalizedAlertSubtitle("Test");
this.builder.setAlertSubtitle("Test");
}

@Test(expected = IllegalStateException.class)
public void testSetLocalizedAlertWithExistingAlertBody() {
this.builder.setAlertBody("Test");
this.builder.setLocalizedAlertMessage("Test", null);
public void testSetLocalizedAlertSubtitleWithExistingAlertSubtitle() {
this.builder.setAlertSubtitle("Test");
this.builder.setLocalizedAlertSubtitle("Test");
}

@Test(expected = IllegalStateException.class)
public void testSetAlertTitleWithExistingLocalizedAlertTitle() {
this.builder.setLocalizedAlertTitle("Test", null);
this.builder.setAlertTitle("Test");
}
@Test
public void testSetAlertTitleAndBody() {
final String alertTitle = "This is a short alert title";
final String alertBody = "This is a longer alert body";

@Test(expected = IllegalStateException.class)
public void testSetLocalizedAlertTitleWithExistingAlertTitle() {
this.builder.setAlertTitle("Test");
this.builder.setLocalizedAlertTitle("Test", null);
this.builder.setAlertBody(alertBody);
this.builder.setAlertTitle(alertTitle);

{
final Map<String, Object> aps = this.extractApsObjectFromPayloadString(this.builder.buildWithDefaultMaximumLength());

@SuppressWarnings("unchecked")
final Map<String, Object> alert = (Map<String, Object>) aps.get("alert");

assertEquals(alertTitle, alert.get("title"));
assertEquals(alertBody, alert.get("body"));
}
}

@Test
Expand Down

0 comments on commit aba34ee

Please sign in to comment.