Airship Java Library

Java library for using Airship’s messaging platform and related features.

Resources

Installation

You can install the Java Library with Maven or manually.

Maven

Add the library using Maven by adding the following lines to your pom.xml:

<!-- Airship Library Dependency-->
<dependency>
    <groupId>com.urbanairship</groupId>
    <artifactId>java-client</artifactId>
    <version>VERSION</version>
    <!-- Replace VERSION with the version you want to use -->
</dependency>

Manual

To install the Java Library manually, clone the repository, run mvn package, and add the jar. The docs can also be built.

Clone the Java Library repo, and build the jar:

mvn package

Add the jar, replacing ‘VERSION’ with your desired version number located at a path similar to:

target/java-client-VERSION.jar

If you would like a copy of the javadocs, use:

mvn javadoc:javadoc

Logging

Add log4j to your pom.xml:

Add log4j to pom.xml
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>VERSION</version>
</dependency>

<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>VERSION</version>
</dependency>

Logging is done using the Simple Logging Facade for Java. Using the logging facade allows for flexibility in logging choices. For example, to use log4j, you would add the following to your pom.xml:

Add log4j as log handler
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.log4j.BasicConfigurator;

Logger logger = LoggerFactory.getLogger("identifier");
// Use any configuration you need.
BasicConfigurator.configure();
logger.debug("Log all the things!");

Note the logging framework plus the adapter. For more info, see the Simple Logging Facade documentation. Simply add the log handler of your choice.

Getting Started

Setting up an Airship Client

The following is the minimum-viable UrbanAirshipClient configuration:

Basic client configuration
UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
    .setKey("your-app-key-here")
    .setSecret("your-app-secret-here")
    .build();

The UrbanAirshipClient handles the interaction between the client and the API. The client will throw an exception if there is an issue with the request, or if it is improperly configured.

Connecting to European Server

Connecting to European Server:

Connect to European server
UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
    .setKey("your-app-key-here")
    .setSecret("your-app-secret-here")
    .setUseEuropeanSite(true)
    .build();

Create a Request

Creating a request to the push API:

Create push request
PushPayload payload = PushPayload.newBuilder()
    .setAudience(Selectors.iosChannel("ios_channel"))
    .setNotification(Notifications.alert("Here's a push!"))
    .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS))
    .build();

PushRequest request = PushRequest.newRequest(payload);

Next, you are going to create a request.

Send the Request

Executing the push request:

Execute push request
Response<PushResponse> response = null;
try {
    response = client.execute(request);
    logger.debug(String.format("Response %s", response.toString()));
} catch (IOException e) {
    logger.error("IOException in API request " + e.getMessage());
}

Once you have created a request, you pass it to be executed in the client created earlier.

The Airship Client

The UrbanAirshipClient class handles requests to the Airship Engage API. This document covers the various configuration options, along with different methods for executing requests within the client. UrbanAirshipClient sets AsyncRequestClient as the underlying HTTP client by default for basic configurations. The AsyncRequestClient can be configured or a different HTTP client can be implemented by extending the RequestCleint interface.

Configuration

Minimum-viable UrbanAirshipClient config

Basic client configuration
UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
    .setKey("your-app-key-here")
    .setSecret("your-app-secret-here")
    .build();

As shown in the Getting Started Guide, the minimum-viable UrbanAirshipClient client configuration requires an app key and a master secret.

In the following sections, we’ll explore some of the additional client configuration options available.

Client With Proxy

Setting the client proxy:

Configuring a proxy
Realm realm = new Realm.Builder("user", "password")
    .setScheme(Realm.AuthScheme.BASIC)
    .build();

ProxyServer proxyServer = new ProxyServer.Builder("test.urbanairship.com", 8080)
    .setRealm(realm)
    .build();

AsyncRequestClient asyncRequestClient = AsyncRequestClient.newBuilder()
    .setProxyServer(proxyServer)
    .build();

UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
    .setKey("key")
    .setSecret("secret")
    .setClient(asyncRequestClient)
    .build();

Optionally, a client can be created with proxy server support.

 

 

 

 

 

Client With HTTP Parameter Settings

Set HTTP parameters:

Set HTTP parameters
DefaultAsyncHttpClientConfig.Builder clientConfigBuilder = new DefaultAsyncHttpClientConfig.Builder()
    .setConnectTimeout(20);

AsyncRequestClient asyncRequestClient = AsyncRequestClient.newBuilder()
    .setClientConfigBuilder(clientConfigBuilder)
    .build();

UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
    .setKey("key")
    .setSecret("secret")
    .setClient(asyncRequestClient)
    .build();

A client can also be created with the option to set any of the HTTP parameters configurable through the Async HTTP client, such as the protocol and connection parameters, by passing in a DefaultAsyncHttpClientConfig.Builder. In the example, the connection timeout is set to be 20 ms, thus overriding the default settings as infinite timeouts.

 

Client with Custom Retry Logic

You may optionally specify a custom retry predicate. This predicate dictates how the client responds to failure, i.e., when should the client retry a failed request. The default retry predicate will retry all requests that return responses with status codes of 500 or higher, assuming they are not POST requests. We avoid retrying POST requests in order to prevent duplicates (e.g., retrying a push request may result in duplicate pushes). Requests are retried a maximum of 10 times, with an exponentially-increasing backoff period between each attempt.

Configure the Predicate to retry:

Configure retries
Predicate<FilterContext> retryPredicate = new Predicate<FilterContext>() {
    @Override
    public boolean apply(FilterContext input) {
        return input.getResponseStatus().getStatusCode() >= 500;
    }
};

In the example, we create a custom predicate that will retry all requests that return responses with status codes of 500 or greater. Unlike the default retry predicated, this predicate will retry POST requests.

 

Set the Predicate to retry:

Set to retry
AsyncRequestClient asyncRequestClient = AsyncRequestClient.newBuilder()
    .setRetryPredicate(retryPredicate)
    .setMaxRetries(20)
    .build();

UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
    .setKey("key")
    .setSecret("secret")
    .setClient(asyncRequestClient)
    .build();

We now configure an UrbanAirshipClient to use the above retryPredicate. We also increase the max number of retry attempts from 10 to 20.

Executing Requests

UrbanAirshipClient different modes of request execution:

Different ways of executing requests
execute(Request<T> request)
execute(Request<T> request, ResponseCallback callback)
executeAsync(Request<T> request)
executeAsync(Request<T> request, ResponseCallback callback)

Once you have a client configured and some sort of request created, the UrbanAirshipClient class supports four different modes of request execution.

 

Making Async Requests

Initiate a non-blocking call:

Initiate a non-blocking call
// Non-blocking request
Future<Response> futureResponse = client.executeAsync(request);

// Do other stuff...

// Retrieve your response after doing stuff.
Response<PushResponse> response = futureResponse.get();

Use the executeAsync(..) method to initiate a non-blocking call to the Airship API.

 

Response Callbacks

Setting ResponseCallback:

Setting a Response Callback
ResponseCallback callback = new ResponseCallback() {
    @Override
    public void completed(Response response) {
        // Logic specifying what to do upon request completion.
        doSomething(response)
    }

    @Override
    public void error(Throwable throwable) {
        // Logic specifying what to do if the request fails.
        doSomethingElse(throwable)
    }
};

Both the execute and executeAsync methods accept an optional ResponseCallback argument. Below, we define a callback that executes the doSomething(...) function once a request completes, and the doSomethingElse(...) function if the request fails.

 

 

 

Example (executeAsync):

Example of an executeAsync request
// Start the request execution. Once the request has completed (or thrown an error),
// the appropriate callback function will be triggered. ``executeAsync`` is non-blocking,
// so you can do other stuff while you wait for the callback to get triggered.
Future<Response> response = client.executeAsync(request, callback)

// Do other stuff...

We can use this callback with either execute or executeAsync:

Example (execute):

Example of an execute request
// Start the request execution . Once the request has completed (or thrown an error),
// the appropriate callback function will be triggered. ``execute`` is blocking, so
// you must wait for the request to complete (or fail), after which the callback is triggered
// and the Response<..> is returned.
Response<PushResponse> response = client.execute(request, callback)

 

 

 

 

Exceptions

Handling exceptions in the ResponseCallback:

ResponseCallback exception handling
ResponseCallback callback = new ResponseCallback() {
    @Override
    public void completed(Response response) {
        // Logic specifying what to do upon request completion.
        doSomething(response)
    }

    @Override
    public void error(Throwable throwable) {
        if (throwable instanceof ClientException) {
            // Handle a 4xx response
        } else if (throwable instance of ServerException)
            // Handle a 5xx response
        } else {
            // Handle any other failure
        }
    }
};

The client will throw different exceptions depending on mode of execution. If you are not using a callback, all exceptions present as RuntimeExceptions. If you choose to use a callback, you can customize the error method to distinguish between ClientExceptions (4xx responses), ServerExceptions (5xx responses), and any other potential failures.

API Endpoint examples

Push

The PushPayload has three components:

  • Audience and Selectors
  • Notifications
  • Device Types

The first is the Audience. The audience is composed of Selectors, which can be compound or atomic (not compound). Selectors provide logical combinations of AND, OR, and NOT.

Audience and Selectors

Send to your audience with kittens tag:

Send to a tag
Selectors.tag("kittens");

The Selectors and DeviceType classes provide factory methods that can be used together to create an Audience Selector.

A more complex audience query:

Complex audience example
Selector andSelector = Selectors.and(Selectors.tag("puppies"), Selectors.tag("kittens"));
Selector notSelector = Selectors.not(Selectors.tag("fish"));
Selector compound = Selectors.or(andSelector, notSelector);

More complex logic is possible.

Notifications

An example of an iOS notification implementing expiry and interactive notifications:

Example send to iOS with expiry and interactive features
PushExpiry expiry = PushExpiry.newBuilder()
    .setExpirySeconds(3600)
    .build();

Interactive interactive = Interactive.newBuilder()
    .setType("ua_yes_no_foreground")
    .setButtonActions(ImmutableMap.of(
        "yes",
        Actions.newBuilder()
            .addTags(new AddTagAction(TagActionData.single("tag1")))
            .build(),
        "no",
        Actions.newBuilder()
            .addTags(new AddTagAction(TagActionData.single("tag2")))
            .build()))
    .build();

IOSDevicePayload iosPayload = IOSDevicePayload.newBuilder()
    .setAlert("alert")
    .setExpiry(expiry)
    .setInteractive(interactive)
    .build();

PushPayload payload = PushPayload.newBuilder()
    .setAudience(Selectors.iosChannel("9c36e8c7-5a73-47c0-9716-99fd3d4197d5"))
    .setNotification(Notifications.notification(iosPayload))
    .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS))
    .build();

Notifications are the second part of the PushPayload. Notifications are configured for each type of device you would like to send a message to. A Notification for an iOS device contains options for alert, badge, sound, content_available, extra, expiry, priority, category, interactive, etc. Other platforms, e.g., Android, may offer different configurations based on available features.

An example of an iOS notification implementing global attributes personalization:

Global attributes example
ArrayList productsList = new ArrayList();

HashMap mMap = new HashMap();
mMap.put("id", 1);
mMap.put("name", "New Line Sneakers");
mMap.put("price","79.95");
productsList.add(mMap);

mMap = new HashMap();
mMap.put("id", 2);
mMap.put("name","Old Line Sneakers");
mMap.put("price","59.95");
productsList.add(mMap);

IOSDevicePayload iosPayload = IOSDevicePayload.newBuilder()
        .setAlert("Hi from Airship!{{#if super_sale }} We're having a sale on {{ products.0.name }}!{{/if}}")
        .addExtraEntry("url","http://www.urbanairship.com")
        .build();

PushOptions myOptions = PushOptions.newBuilder()
        .setPersonalization(true)
        .build();

PushPayload payload = PushPayload.newBuilder()
        .setAudience(Selectors.or(Selectors.iosChannel("9c36e8c7-5a73-47c0-9716-99fd3d4197d5"), Selectors.tags("sports","entertainment")))
        .setNotification(Notifications.notification(iosPayload))
        .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS))
        .addGlobalAttributes("products", productsList)
        .addGlobalAttributes("super_sale",true)
        .setPushOptions(myOptions)
        .build();

An example of an iOS notification implementing media attachment and some specific iOS options:

Media attachment and special iOS options example
IOSAlertData iosAlert = IOSAlertData.newBuilder()
        .setTitle("Kevin Gausman Throws a Perfect Game")
        .setBody("Kevin Gausman stymies the Houston Astros for San Francisco's second perfect game in franchise history.")
        .setSummaryArg("San Francisco Giants")
        .setSummaryArgCount(1)
        .build();

IOSMediaContent iosMediaContent = IOSMediaContent.newBuilder()
        .setBody("Kevin Gausman")
        .setBody("Gausman strikes out Justin Turner")
        .build();

IOSMediaOptions iosMediaOptions = IOSMediaOptions.newBuilder()
        .setCrop(Crop.newBuilder()
                .setHeight(BigDecimal.valueOf(0.5))
                .setWidth(BigDecimal.valueOf(0.5))
                .setX(BigDecimal.valueOf(0.25))
                .setY(BigDecimal.valueOf(0.25))
                .build())
        .setTime(15)
        .build();

MediaAttachment mediaAttachment = MediaAttachment.newBuilder()
        .setContent(iosMediaContent)
        .setOptions(iosMediaOptions)
        .setUrl("https://media.giphy.com/media/6nJmrhlu4aL1m/giphy.gif")
        .build();

IOSDevicePayload iOSPayload = IOSDevicePayload.newBuilder()
        .setThreadId("sfGiants_news")
        .setAlert(iosAlert)
        .setRelevanceScore(1.0)
        .setIosInterruptionLevel(IOSInterruptionLevel.PASSIVE)
        .setSoundData(IOSSoundData.newBuilder().setName("strike-call").build())
        .setMediaAttachment(mediaAttachment)
        .setMutableContent(true)
        .build();

PushPayload pushPayload = PushPayload.newBuilder()
        .setAudience(Selectors.all())
        .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS))
        .setNotification(Notifications.notification(iOSPayload))
        .build();

 

 

 

 

Device Types

Here’s an example of setting the device types to iOS and Android:

Setting device types to target
DeviceTypeData deviceTypeData  = DeviceTypeData.of(DeviceType.IOS, DeviceType.ANDROID);

The final part of the PushPayload is DeviceTypes, which defines the platform you’re sending to, e.g., iOS or Android. Messages can be segregated by device types. Set the device types you want to send to using a DeviceTypeData object.

Schedules

Create a Scheduled Notification

Scheduling a push notification:

Schedule a push
SchedulePayload schedulePayload = SchedulePayload.newBuilder()
        .setName("Morning People")
        .setSchedule(Schedule.newBuilder()
                .setScheduledTimestamp(DateTime.parse("2020-06-03T09:15:00Z"))
                .build())
        .setPushPayload(PushPayload.newBuilder()
                .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS, DeviceType.ANDROID))
                .setNotification(Notifications.alert("Good Day Sunshine"))
                .setAudience(Selectors.tag("earlyBirds"))
                .build())
        .build();

ScheduleRequest scheduleRequest = ScheduleRequest.newRequest(schedulePayload);
Response<ScheduleResponse> response = client.execute(scheduleRequest);

You can use the ScheduleRequest.newRequest(<schedule_payload>) method to create a scheduled notification.  

 

 

Update a Schedule

Updating a scheduled notification:

Update a scheduled push
SchedulePayload schedulePayload = SchedulePayload.newBuilder()
        .setName("I would like to subscribe to your newsletter")
        .setSchedule(Schedule.newBuilder()
                .setScheduledTimestamp(DateTime.parse("2020-04-01T18:45:00Z"))
                .build())
        .setPushPayload(PushPayload.newBuilder()
                .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS, DeviceType.ANDROID))
                .setNotification(Notifications.alert("Check your inbox!"))
                .setAudience(Selectors.tag("intriguing"))
                .build())
        .build();

ScheduleRequest scheduleRequest = ScheduleRequest.newUpdateRequest(schedulePayload, "5cde3564-ead8-9743-63af-821e12337812");
Response<ScheduleResponse> response = client.execute(scheduleRequest);

You can use the ScheduleRequest.newUpdateRequest(<schedule_payload> "<schedule_id>") method to update a scheduled notification.  

 

 

Lookup Schedule

Looking up a scheduled notification:

Look up a scheduled push
ScheduleListingRequest request = ScheduleListingRequest.newRequest("5cde3564-ead8-9743-63af-821e12337812");
Response<ListAllSchedulesResponse> response = client.execute(request);
SchedulePayloadResponse schedule = response.getBody().get().getSchedules().get(0);

// Get the schedule's name
Optional<String> name = schedule.getName();
// Get the push IDs
Set<String> pushIds = schedule.getPushIds();
// Get the scheduled time
Schedule sched = schedule.getSchedule();
// Get the associated push payload
PushPayload payload = schedule.getPushPayload();
// Get the URL
Optional<String> url = schedule.getUrl();

To lookup a schedule, use the ScheduleListingRequest.newRequest("<schedule_id>") method.

 

 

 

List Schedules

List all scheduled notifications:

List scheduled pushes
ScheduleListingRequest request = ScheduleListingRequest.newRequest();
Response<ListAllSchedulesResponse> response = client.execute(request);

// Get the list of schedules
List<SchedulePayloadResponse> schedules = response.getBody().get().getSchedules();

To view a list of all created schedules, use the ScheduleListingRequest.newRequest() method.

Delete Schedule

Delete schedule request:

Delete a scheduled push
ScheduleDeleteRequest request = ScheduleDeleteRequest.newRequest("schedule_1234");
Response<GenericResponse> response = client.execute(request);

To delete a schedule, use the ScheduleDeleteRequest.newRequest("<schedule_id>") method.

A/B Tests

Create A/B Tests

Create an A/B Test with a schedule time:

Schedule an A/B test
Schedule schedule = Schedule.newBuilder()
                .setScheduledTimestamp(DateTime.now().plusDays(1))
                .build();

Variant variantOne = Variant.newBuilder()
        .setPushPayload(VariantPushPayload.newBuilder()
                .setNotification(Notification.newBuilder()
                        .setAlert("Hello there!")
                        .build()
                )
                .build())
        .setSchedule(schedule)
        .build();

Variant variantTwo = Variant.newBuilder()
        .setPushPayload(VariantPushPayload.newBuilder()
                .setNotification(Notification.newBuilder()
                        .setAlert("Boogaloo")
                        .build()
                )
                .build())
        .setSchedule(schedule)
        .build();

Experiment experiment = Experiment.newBuilder()
        .setName("Another test")
        .setDescription("Its a test!")
        .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS))
        .setAudience(Selectors.namedUser("NamedUserID"))
        .addVariant(variantOne)
        .addVariant(variantTwo)
        .build();

ExperimentRequest request = ExperimentRequest.newRequest(experiment);
Response<ExperimentResponse> response = client.execute(request);

To create an A/B Test, use the ExperimentRequest.newRequest() method.

 

 

 

 

 

 

 

 

 

 

 

 

Delete A/B Tests

Delete a scheduled A/B Test:

Delete a scheduled A/B test
ExperimentDeleteRequest experimentDeleteRequest = ExperimentDeleteRequest.newRequest("experimentId");
Response<ExperimentResponse> response = client.execute(experimentDeleteRequest);

To delete a scheduled A/B Test, use the ExperimentDeleteRequest.newRequest() method.

Note that experiments can only be deleted before they start.

Personalization

Create Template

Create a template:

Create a template
TemplateVariable titleVariable = TemplateVariable.newBuilder()
        .setKey("TITLE")
        .setName("Title")
        .setDescription("e.g. Mr, Ms, Dr, etc")
        .setDefaultValue("")
        .build();

TemplateVariable firstNameVariable = TemplateVariable.newBuilder()
        .setKey("FIRST_NAME")
        .setName("First Name")
        .setDescription("Given name")
        .setDefaultValue(null)
        .build();

TemplateVariable lastNameVariable = TemplateVariable.newBuilder()
        .setKey("LAST_NAME")
        .setName("Last Name")
        .setDescription("Family name")
        .setDefaultValue("")
        .build();

PartialPushPayload partialPushPayload = PartialPushPayload.newBuilder()
        .setNotification(Notification.newBuilder()
                .setAlert("Hello {{TITLE}} {{FIRST_NAME}} {{LAST_NAME}}, welcome to our loyalty program!")
                .build()
        )
        .build();

TemplateRequest request = TemplateRequest.newRequest()
        .setName("Template Name")
        .setDescription("A description")
        .addVariable(titleVariable)
        .addVariable(firstNameVariable)
        .addVariable(lastNameVariable)
        .setPush(partialPushPayload);

Response<TemplateResponse> response = client.execute(request);

To create a template, use the TemplateRequest.newRequest() method.

 

 

 

 

 

 

 

 

 

 

 

 

Update Template

Update an existing template:

Update a template
PartialPushPayload partialPushPayload = PartialPushPayload.newBuilder()
        .setNotification(Notification.newBuilder()
                .setAlert("Hello {{FIRST_NAME}} {{LAST_NAME}}, this is a test!")
                .build()
        )
        .build();

TemplateRequest request = TemplateRequest.newRequest(UUID.randomUUID().toString())
        .setName("your-template-name")
        .setPush(partialPushPayload);

Response<TemplateResponse> response = client.execute(request);

To update a template, use the TemplateRequest.newRequest(<template-id>) method.

 

 

 

Push to Template

In the example below, we push to the template we created in the Create Template section:

Send a push using a template
TemplatePushPayload payload = TemplatePushPayload.newBuilder()
        .setAudience(Selectors.namedUser("named-user"))
        .setDeviceTypes(DeviceTypeData.of(DeviceType.ANDROID))
        .setMergeData(TemplateSelector.newBuilder()
                .setTemplateId("template-id-123")
                .addSubstitution("FIRST_NAME", "James")
                .addSubstitution("LAST_NAME", "Brown")
                .addSubstitution("TITLE", "Mr.")
                .build())
        .build();

TemplatePushRequest request = TemplatePushRequest.newRequest()
        .addTemplatePushPayload(payload);

Response<TemplateResponse> response = client.execute(request);

To push to a template, use the TemplatePushRequest.newRequest() method.

 

 

 

 

 

Template Lookup

Template lookup:

Look up a template
TemplateListingRequest request = TemplateListingRequest.newRequest("template-id");
Response<TemplateListingResponse> response = client.execute(request);

To look up a template, use the TemplateListingRequest.newRequest("template-id") method.

Template Listing

List all Templates:

List templates
TemplateListingRequest request = TemplateListingRequest.newRequest();
Response<TemplateListingResponse> response = client.execute(request);

To list all templates, use the TemplateListingRequest.newRequest() method:

Delete Template

Delete a Template:

Delete a template
TemplateDeleteRequest request = TemplateDeleteRequest.newRequest("template-id");
Response<TemplateResponse> response = client.execute(request);

To delete a template, use the TemplateDeleteRequest.newRequest("template-id") method.

Audience Management

Channels

Lookup Channel

Look up an individual channel:

Look up a channel
ChannelRequest request = ChannelRequest.newRequest("channel_id_123");
Response<ChannelResponse> response = client.execute(request);
ChannelView channel = response.getBody().get().getChannelView().get();

// The channel ID
String channelId = channel.getChannelId();
// The channel type -- one of IOS, ANDROID, or ADM
String channelType = channel.getChannelType();
// Whether the channel is installed or not
boolean installed = channel.isInstalled();
// Whether the channel is opted in to push or not
boolean optedIn = channel.isOptIn();
// Whether background push is enabled on the device
Optional<Boolean> background = channel.getBackground();
// The push address associated with the channel
Optional<String> pushAddress = channel.getPushAddress();
// When the channel was created
DateTime created = channel.getCreated();
// The date at which the channel was last registered
DateTime lastRegistration = channel.getLastRegistration();
// The alias (potentially) associated with the channel
Optional<String> alias = channel.getAlias();
// The tags associated with the channel
ImmutableSet<String> tags = channel.getTags();
// The tag groups associated with the channel
ImmutableMap<String, ImmutableSet<String>> tagGroups = channel.getTagGroups();
// An IosSettings object
Optional<IosSettings> iosSettings = channel.getIosSettings();

To lookup a specific channel, use the ChannelRequest.newRequest("<channel_id>") method.

 

 

 

 

 

 

 

 

 

List Channels

List all channels:

List channels
ChannelRequest request = ChannelRequest.newRequest();
Response<ChannelResponse> response = client.execute(request);
ChannelView channels = response.getBody().get().getChannelView().get();

To list all channels, use the ChannelRequest.newRequest() method.

Named Users

Associate Named User

Associate channel to named user:

Associate a channel to a named user
NamedUserRequest request = NamedUserRequest.newAssociationRequest()
        .setChannel("ee4b5101-164c-485c-ad91-68b1d3d753cc", ChannelType.IOS)
        .setNamedUserId("id-1234");

Response<GenericResponse> response = client.execute(request);

To associate channels to a Named User, use the NamedUserRequest class.

 

Disassociate Named User

Disassociate channel from named user:

Disassociate a channel from a named user
NamedUserRequest request = NamedUserRequest.newDisassociationRequest()
        .setChannel("0ab7d6f0-0f61-4963-afe0-5ef53735b00d", ChannelType.ANDROID);

Response<GenericResponse> response = client.execute(request);

To disassociate channels from a Named User, use the NamedUserRequest class.

Look up a Named User

Look up a named user:

Look up a named user
NamedUserListingRequest request = NamedUserListingRequest.newRequest("id-1234");
Response<NamedUserListingResponse> response = client.execute(request);
NamedUserView namedUser = response.getBody().get().getNamedUserView().get();

// The named user ID
String namedUserId = namedUser.getNamedUserId();
// Map of tag groups and the associated sets of tags
ImmutableMap<String, ImmutableSet<String>> namedUserTags = namedUser.getNamedUserTags();
// All channel objects associated with the named user
ImmutableSet<ChannelView> channelViews = namedUser.getChannelViews();

To lookup a named user, use the NamedUserListRequest.newRequest("<named_user_id>") method.

 

 

List Named Users

List named users:

List named users
NamedUserListingRequest request = NamedUserListingRequest.newRequest();
Response<NamedUserListingResponse> response = client.execute(request);
ImmutableList<NamedUserView> namedUsers = response.getBody().get().getNamedUserViews().get();

To list named users, use the NamedUserListRequest.newRequest() method.

Tags

See: Tags: Named Users

Add/Remove Tags From Channel

Channel Tags:

Set up a channel tag request
Set<String> tags = new HashSet<String>();
tags.add("loyalty");
tags.add("platinum");
tags.add("sports");

Set<String> remove = new HashSet<String>();
tags.add("gold");
tags.add("news");

ChannelTagRequest request = ChannelTagRequest.newRequest()
    .addIOSChannels("56071f7c-921f-4981-9568-b5f7cef427cd", "a74897b2-3ff3-4741-8b69-1d739fc3830f")
    .addAndroidChannel("ecf68576-c7ac-48cc-9aaa-94b63e6dccda")
    .addTags("device", tags)
    .removeTags("device", remove);

Response<GenericResponse> response = client.execute(request);

To add tags use the ChannelTagRequest class. In the following example, we add the tags loyalty, platinum, and sports, and remove the tags gold and news.

 

 

 

 

Add/Remove Tags From Named Users

To execute tag operations on a named user, use the NamedUserTagRequest class.

Add Tags:

Add tags
Set<String> tags = new HashSet<String>();
tags.add("loyalty");
tags.add("platinum");
tags.add("sports");

NamedUserTagRequest request = NamedUserTagRequest.newRequest()
        .addNamedUsers("user-1", "user-2", "user-3")
        .addTags("device", tags);
Response<GenericResponse> response = client.execute(request);

The addTags("<tag_group>", <tag_set>) method is used for adding tags.

 

 

 

Remove Tags:

Remove tags
Set<String> tags = new HashSet<String>();
tags.add("loyalty");
tags.add("platinum");
tags.add("sports");

NamedUserTagRequest request = NamedUserTagRequest.newRequest()
        .addNamedUsers("user-1", "user-2", "user-3")
        .removeTags("device", tags);
Response<GenericResponse> response = client.execute(request);

The removeTags("<tag_group>", <tag_set>) method is used for removing tags.

 

 

 

Set Tags:

Set tags
Set<String> tags = new HashSet<String>();
tags.add("loyalty");
tags.add("platinum");
tags.add("sports");

NamedUserTagRequest request = NamedUserTagRequest.newRequest()
        .addNamedUsers("user-1", "user-2", "user-3")
        .setTags("device", tags);
Response<GenericResponse> response = client.execute(request);

The setTags("<tag_group>", <tag_set>) method is used to wipe the current set of tags on the device with the provided set.

Segments

Create Segment

Create a Segment:

Create a segment
SegmentRequest request = SegmentRequest.newRequest();

// Define the segment criteria
Selector andSelector = Selectors.tags("java", "lib");
Selector compound = Selectors.or(andSelector, Selectors.not(Selectors.tag("mfd")));
DateRange dateRange = Selectors.weeks(3);
Selector location = Selectors.location("us_zip", "97214", dateRange);
Selector locationCriteria = Selectors.or(compound, location);

// Set the request criteria and display name, and execute the request.
request.setCriteria(locationCriteria);
request.setDisplayName("UAJavaLib");
Response<GenericResponse> response = client.execute(request);

To create a segment, use the SegmentRequest.newRequest() method.

 

 

 

Look up a Segment

Look up a Segment:

Look up a segment
SegmentLookupRequest request = SegmentLookupRequest.newRequest("<segment_id>");
Response<SegmentView> response = client.execute(request);

// Get the segment criteria
Selector criteria = response.getBody().get().getCriteria();
// Get the segment display name
String displayName = response.getBody().get().getDisplayName();

To get information on a particular segment, use the SegmentLookupRequest.newRequest("<segment_id>") method.

 

List Segments

List all Segments:

List segments
SegmentListingRequest request = SegmentListingRequest.newRequest();
Response<SegmentListingResponse> response = client.execute(request);

// Get the first segment in the list
SegmentListingView segment = response.getBody().get().getSegmentListingViews().get(0);

// Get the segment display name
String displayName = segment.getDisplayName();

// Get the segment ID
String id = segment.getSegmentId();

To get a list of all segments, use the SegmentListingRequest.newRequest() method.

 

 

 

Update Segment

Update a segment:

Update a segment
SegmentRequest request = SegmentRequest.newUpdateRequest("<segment_id>");

// Define the segment criteria
Selector andSelector = Selectors.tags("java", "lib");
Selector compound = Selectors.or(andSelector, Selectors.not(Selectors.tag("mfd")));
DateRange dateRange = Selectors.weeks(3);
Selector location = Selectors.location("us_zip", "97214", dateRange);
Selector locationCriteria = Selectors.or(compound, location);

// Set the request criteria and display name, and execute the request.
request.setCriteria(locationCriteria);
request.setDisplayName("UAJavaLib");
Response<GenericResponse> response = client.execute(request);

To update a segment, use the SegmentRequest.newUpdateRequest("<segment_id>") method.

 

 

Delete Segment

Delete a segment:

Delete a segment
SegmentDeleteRequest request = SegmentDeleteRequest.newRequest("<segment_id>");
Response<GenericResponse> response = client.execute(request);

To delete a segment, use the SegmentDeleteRequest.newRequest("<segment_id>") method.

Static Lists

Create Static List

Create a static list:

Create a static list
StaticListRequest request = StaticListRequest.newRequest("platinum_members")
        .setDescription("Subscribers with platinum status.")
        .addExtra("cool", "extras")
        .addExtra("another", "extra");

Response<GenericResponse> response = client.execute(request);

To create a static list, use the StaticListRequest.newRequest("<list_name>") method.

Upload Static List

Upload a static list:

Upload a static list
File dataDirectory = new File("src/data");
String filePath = dataDirectory.getAbsolutePath() + "/platinum.csv";
StaticListUploadRequest request = StaticListUploadRequest.newRequest("platinum_members", filePath);
Response<GenericResponse> response = client.execute(request);

To upload a static list, use the StaticListUploadRequest.newRequest("<list_name>", "<file_path>") method.

Download Static List

Download the CSV associated with a static list:

Download static list CSV
StaticListDownloadRequest request = StaticListDownloadRequest.newRequest("<list_name>");
Response<String> response = client.execute(request);

To download the CSV associated with a static list, use the StaticListDownloadRequest.newRequest("<list_name>") method.

 

Direct the output to FileOutputStream:

Direct static list CSV download to FileOutputStream
FileOutputStream fileOutputStream = new FileOutputStream(new File("list.csv"));

StaticListDownloadRequest request = StaticListDownloadRequest.newRequest("<list_name>")
    .setOutputStream(fileOutputStream);
Response<String> response = client.execute(request);

Optionally, you can direct the output to a FileOutputStream by using the setResponseFile setter.

 

 

Download a Lifecycle list:

Download a lifecycle list
StaticListDownloadRequest request = StaticListDownloadRequest.newRequest(LifecycleListType.UNINSTALLS_LAST_MONTH)
    .setOutputStream(fileOutputStream);
Response<String> response = client.execute(request);

You can also call the StaticListDownloadRequest.newRequest() method with one of the Lifecycle List types defined in the LifecycleListType enum.

Reports

Platform Statistics

Optionally, you can direct the output to a FileOutputStream by using the setResponseFile setter.

Platform Statistic Reports:

Getting platform statistic reports
DateTime start = new DateTime(2015, 10, 1, 12, 0, 0, 0);
DateTime end = start.plus(Period.hours(48));

// App Opens Report
PlatformStatsRequest appOpensRequest = PlatformStatsRequest.newRequest(PlatformStatsRequestType.APP_OPENS)
    .setStart(start)
    .setEnd(end)
    .setPrecision(Precision.HOURLY);

// Time in App Report
PlatformStatsRequest tiaRequest = PlatformStatsRequest.newRequest(PlatformStatsRequestType.TIME_IN_APP)
    .setStart(start)
    .setEnd(end)
    .setPrecision(Precision.HOURLY);

// Opt-ins Report
PlatformStatsRequest optInsRequest = PlatformStatsRequest.newRequest(PlatformStatsRequestType.OPT_INS)
    .setStart(start)
    .setEnd(end)
    .setPrecision(Precision.HOURLY);

// Opt-outs Report
PlatformStatsRequest optOutsRequest = PlatformStatsRequest.newRequest(PlatformStatsRequestType.OPT_OUTS)
    .setStart(start)
    .setEnd(end)
    .setPrecision(Precision.HOURLY);

// Push Report
PlatformStatsRequest pushSendsRequest = PlatformStatsRequest.newRequest(PlatformStatsRequestType.SENDS)
    .setStart(start)
    .setEnd(end)
    .setPrecision(Precision.HOURLY);

Response<PlatformStatsResponse> appOpensResponse = client.execute(appOpensRequest);
Response<PlatformStatsResponse> tiaResponse = client.execute(tiaRequest);
Response<PlatformStatsResponse> optInsResponse = client.execute(optInsRequest);
Response<PlatformStatsResponse> optOutsResponse = client.execute(optOutsRequest);
Response<PlatformStatsResponse> pushSendsResponse = client.execute(pushSendsRequest);

PlatformStats stats = appOpensResponse.getBody().get().getPlatformStatsObjects().get().get(0);
// Get the number of iOS devices
int ios = stats.getIos();
// Get the number of Android devices
int android = stats.getAndroid();
// Get the time interval
DateTime date = stats.getDate();

The various reports that provide platform feedback are all handled by the PlatformStatsRequest class. This group of reports includes the App Opens Report, Time in App Report, Opt-ins Report, Opt-outs Report, and Push Reports. Each of the following requests requires a start date, end date, and precision.

Individual Push Response Statistics

Individual Push Response Statistics request:

Get the push response statistics report
PushInfoRequest request = PushInfoRequest.newRequest("ca15a452-ad5d-4bd9-95bb-e190eeba32cd");
Response<PushInfoResponse> response = client.execute(request);
PushInfoResponse pushInfo = response.getBody().get();

// Number of sends
int sends = pushInfo.getSends();
// Number of direct responses to the push
int directResponses = pushInfo.getDirectResponses();
// When the push was sent
DateTime date = pushInfo.getPushTime();
// The push type -- can be one of BROADCAST_PUSH, SCHEDULED_PUSH, TAG_PUSH, UNICAST_PUSH
PushType type = pushInfo.getPushType();
// The unique identifier for the push
UUID pushId = pushInfo.getPushId();
// The (optional) group ID
Optional<UUID> groupId = pushInfo.getGroupID();

Use the PushInfoRequest.newRequst("<push_id>") class to get information on a particular push id.

Response Listing

Response Listing request:

Get the response listing report
DateTime start = new DateTime(2015, 10, 1, 12, 0, 0, 0);
DateTime end = start.plus(Period.hours(48));

PushListingRequest request = PushListingRequest.newRequest()
    .setStart(start)
    .setEnd(end)
    .setLimit(20);

Response<PushListingResponse> response = client.execute(request);

// Get the first item in an array of push info responses. You can use all of the getters
// listed in the "Individual Push Response Statistics" section.
PushInfoResponse pushInfo = response.getBody().get().getPushInfoList().get().get(0);

The PushListingRequest class is used to make requests to the /api/reports/responses/list endpoint.

Custom Events

Setting your bearer token:

Set up a bearer token
UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
    .setKey("your-app-key-here")
    .setSecret("your-app-secret-here")
    .setBearerToken("your-bearer-token-here")
    .build();

You must set a bearer token on the UrbanAirshipClient for custom events requests. If only custom event requests are being made, the secret is optional.

Create a custom event:

Create a custom event
// Airship channel identifier for the user who triggered the event.
CustomEventUser customEventUser = CustomEventUser.newBuilder()
                .setCustomEventChannelType(CustomEventChannelType.ANDROID_CHANNEL)
                .setChannel("e393d28e-23b2-4a22-9ace-dc539a5b07a8")
                .build();

// The body object which describes the user action.
CustomEventBody customEventBody = CustomEventBody.newBuilder()
        .setName("purchased")
        .setValue(new BigDecimal(120.49))
        .setTransaction("886f53d4-3e0f-46d7-930e-c2792dac6e0a")
        .setInteractionId("your.store/us/en_us/pd/shoe/pid-11046546/pgid-10978234")
        .setInteractionType("url")
        .setSessionId("22404b07-3f8f-4e42-a4ff-a996c18fa9f1")
        .build();

// The date and time when the event occurred.
DateTime occurred = new DateTime(2015, 5, 2, 2, 31, 22, DateTimeZone.UTC);


CustomEventPayload customEventPayload = CustomEventPayload.newBuilder()
        .setCustomEventBody(customEventBody)
        .setCustomEventUser(customEventUser)
        .setOccurred(occurred)
        .build();

CustomEventRequest customEventRequest = CustomEventRequest.newRequest(customEventPayload);

Response<CustomEventResponse> response = client.execute(customEventRequest);

To create a custom event, use the CustomEventRequest.newRequest() method: