# Server Libraries
Server libraries for using the Airship REST API.
# Airship Java Library
> Java library for using Airship's messaging platform and related features.## Resources
- [Github Repo](https://github.com/urbanairship/java-library)
- [Javadocs](https://www.airship.com/docs/reference/libraries/java/latest/)
- [Airship API Reference](https://www.airship.com/docs/developer/rest-api/ua/)
## 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:
```xml
com.urbanairship
java-client
VERSION
```
### 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**
```xml
org.slf4j
slf4j-log4j12
VERSION
log4j
log4j
VERSION
```
Logging is done using the [Simple Logging Facade for Java](https://www.slf4j.org/). 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**
```java
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](https://www.slf4j.org/manual.html). 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**
```java
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**
```java
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**
```java
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**
```java
Response 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**
```java
UrbanAirshipClient client = UrbanAirshipClient.newBuilder()
.setKey("your-app-key-here")
.setSecret("your-app-secret-here")
.build();
```
As shown in the [Getting Started Guide](#getting-started), 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**
```java
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**
```java
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](https://static.javadoc.io/org.asynchttpclient/async-http-client/2.0.38/org/asynchttpclient/DefaultAsyncHttpClientConfig.Builder.html), 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**
```java
Predicate retryPredicate = new Predicate() {
@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**
```java
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**
```java
execute(Request request)
execute(Request request, ResponseCallback callback)
executeAsync(Request request)
executeAsync(Request 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**
```java
// Non-blocking request
Future futureResponse = client.executeAsync(request);
// Do other stuff...
// Retrieve your response after doing stuff.
Response 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**
```java
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**
```java
// 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 = client.executeAsync(request, callback)
// Do other stuff...
```
We can use this callback with either execute or executeAsync:
> Example (execute):
**Example of an execute request**
```java
// 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 response = client.execute(request, callback)
```
#### Exceptions
> Handling exceptions in the ResponseCallback:
**ResponseCallback exception handling**
```java
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**
```java
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**
```java
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**
```java
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**
```java
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**
```java
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.example.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**
```java
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**
```java
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 response = client.execute(scheduleRequest);
```
You can use the `ScheduleRequest.newRequest()` method to create a scheduled notification.
#### Update a Schedule
> Updating a scheduled notification:
**Update a scheduled push**
```java
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 response = client.execute(scheduleRequest);
```
You can use the `ScheduleRequest.newUpdateRequest( "")` method to update a scheduled notification.
#### Lookup Schedule
> Looking up a scheduled notification:
**Look up a scheduled push**
```java
ScheduleListingRequest request = ScheduleListingRequest.newRequest("5cde3564-ead8-9743-63af-821e12337812");
Response response = client.execute(request);
SchedulePayloadResponse schedule = response.getBody().get().getSchedules().get(0);
// Get the schedule's name
Optional name = schedule.getName();
// Get the push IDs
Set pushIds = schedule.getPushIds();
// Get the scheduled time
Schedule sched = schedule.getSchedule();
// Get the associated push payload
PushPayload payload = schedule.getPushPayload();
// Get the URL
Optional url = schedule.getUrl();
```
To lookup a schedule, use the `ScheduleListingRequest.newRequest("")` method.
#### List Schedules
> List all scheduled notifications:
**List scheduled pushes**
```java
ScheduleListingRequest request = ScheduleListingRequest.newRequest();
Response response = client.execute(request);
// Get the list of schedules
List 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**
```java
ScheduleDeleteRequest request = ScheduleDeleteRequest.newRequest("schedule_1234");
Response response = client.execute(request);
```
To delete a schedule, use the `ScheduleDeleteRequest.newRequest("")` method.
### A/B Tests
#### Create A/B Tests
> Create an A/B Test with a schedule time:
**Schedule an A/B test**
```java
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 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**
```java
ExperimentDeleteRequest experimentDeleteRequest = ExperimentDeleteRequest.newRequest("experimentId");
Response 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**
```java
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 response = client.execute(request);
```
To create a template, use the `TemplateRequest.newRequest()` method.
#### Update Template
> Update an existing template:
**Update a template**
```java
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 response = client.execute(request);
```
To update a template, use the `TemplateRequest.newRequest()` 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**
```java
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 response = client.execute(request);
```
To push to a template, use the `TemplatePushRequest.newRequest()` method.
#### Template Lookup
> Template lookup:
**Look up a template**
```java
TemplateListingRequest request = TemplateListingRequest.newRequest("template-id");
Response response = client.execute(request);
```
To look up a template, use the `TemplateListingRequest.newRequest("template-id")` method.
#### Template Listing
> List all Templates:
**List templates**
```java
TemplateListingRequest request = TemplateListingRequest.newRequest();
Response response = client.execute(request);
```
To list all templates, use the `TemplateListingRequest.newRequest()` method:
#### Delete Template
> Delete a Template:
**Delete a template**
```java
TemplateDeleteRequest request = TemplateDeleteRequest.newRequest("template-id");
Response 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**
```java
ChannelRequest request = ChannelRequest.newRequest("channel_id_123");
Response 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 background = channel.getBackground();
// The push address associated with the channel
Optional 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 alias = channel.getAlias();
// The tags associated with the channel
ImmutableSet tags = channel.getTags();
// The tag groups associated with the channel
ImmutableMap> tagGroups = channel.getTagGroups();
// An IosSettings object
Optional iosSettings = channel.getIosSettings();
```
To lookup a specific channel, use the `ChannelRequest.newRequest("")` method.
#### List Channels
> List all channels:
**List channels**
```java
ChannelRequest request = ChannelRequest.newRequest();
Response 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**
```java
NamedUserRequest request = NamedUserRequest.newAssociationRequest()
.setChannel("ee4b5101-164c-485c-ad91-68b1d3d753cc", ChannelType.IOS)
.setNamedUserId("id-1234");
Response 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**
```java
NamedUserRequest request = NamedUserRequest.newDisassociationRequest()
.setChannel("0ab7d6f0-0f61-4963-afe0-5ef53735b00d", ChannelType.ANDROID);
Response 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**
```java
NamedUserListingRequest request = NamedUserListingRequest.newRequest("id-1234");
Response 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> namedUserTags = namedUser.getNamedUserTags();
// All channel objects associated with the named user
ImmutableSet channelViews = namedUser.getChannelViews();
```
To lookup a named user, use the `NamedUserListRequest.newRequest("")` method.
#### List Named Users
> List named users:
**List named users**
```java
NamedUserListingRequest request = NamedUserListingRequest.newRequest();
Response response = client.execute(request);
ImmutableList namedUsers = response.getBody().get().getNamedUserViews().get();
```
To list named users, use the `NamedUserListRequest.newRequest()` method.
### Tags
See: [Tags: Named Users](#add-remove-tags-from-named-users)
#### Add/Remove Tags From Channel
> Channel Tags:
**Set up a channel tag request**
```java
Set tags = new HashSet();
tags.add("loyalty");
tags.add("platinum");
tags.add("sports");
Set remove = new HashSet();
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 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**
```java
Set tags = new HashSet();
tags.add("loyalty");
tags.add("platinum");
tags.add("sports");
NamedUserTagRequest request = NamedUserTagRequest.newRequest()
.addNamedUsers("user-1", "user-2", "user-3")
.addTags("device", tags);
Response response = client.execute(request);
```
The `addTags("", )` method is used for adding tags.
> Remove Tags:
**Remove tags**
```java
Set tags = new HashSet();
tags.add("loyalty");
tags.add("platinum");
tags.add("sports");
NamedUserTagRequest request = NamedUserTagRequest.newRequest()
.addNamedUsers("user-1", "user-2", "user-3")
.removeTags("device", tags);
Response response = client.execute(request);
```
The `removeTags("", )` method is used for removing tags.
> Set Tags:
**Set tags**
```java
Set tags = new HashSet();
tags.add("loyalty");
tags.add("platinum");
tags.add("sports");
NamedUserTagRequest request = NamedUserTagRequest.newRequest()
.addNamedUsers("user-1", "user-2", "user-3")
.setTags("device", tags);
Response response = client.execute(request);
```
The `setTags("", )` 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**
```java
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 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**
```java
SegmentLookupRequest request = SegmentLookupRequest.newRequest("");
Response 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("")` method.
#### List Segments
> List all Segments:
**List segments**
```java
SegmentListingRequest request = SegmentListingRequest.newRequest();
Response 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**
```java
SegmentRequest request = SegmentRequest.newUpdateRequest("");
// 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 response = client.execute(request);
```
To update a segment, use the `SegmentRequest.newUpdateRequest("")` method.
#### Delete Segment
> Delete a segment:
**Delete a segment**
```java
SegmentDeleteRequest request = SegmentDeleteRequest.newRequest("");
Response response = client.execute(request);
```
To delete a segment, use the `SegmentDeleteRequest.newRequest("")` method.
### Static Lists
#### Create Static List
> Create a static list:
**Create a static list**
```java
StaticListRequest request = StaticListRequest.newRequest("platinum_members")
.setDescription("Subscribers with platinum status.")
.addExtra("cool", "extras")
.addExtra("another", "extra");
Response response = client.execute(request);
```
To create a static list, use the `StaticListRequest.newRequest("")` method.
#### Upload Static List
> Upload a static list:
**Upload a static list**
```java
File dataDirectory = new File("src/data");
String filePath = dataDirectory.getAbsolutePath() + "/platinum.csv";
StaticListUploadRequest request = StaticListUploadRequest.newRequest("platinum_members", filePath);
Response response = client.execute(request);
```
To upload a static list, use the `StaticListUploadRequest.newRequest("", "")` method.
#### Download Static List
> Download the CSV associated with a static list:
**Download static list CSV**
```java
StaticListDownloadRequest request = StaticListDownloadRequest.newRequest("");
Response response = client.execute(request);
```
To download the CSV associated with a static list, use the `StaticListDownloadRequest.newRequest("")` method.
> Direct the output to FileOutputStream:
**Direct static list CSV download to FileOutputStream**
```java
FileOutputStream fileOutputStream = new FileOutputStream(new File("list.csv"));
StaticListDownloadRequest request = StaticListDownloadRequest.newRequest("")
.setOutputStream(fileOutputStream);
Response 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**
```java
StaticListDownloadRequest request = StaticListDownloadRequest.newRequest(LifecycleListType.UNINSTALLS_LAST_MONTH)
.setOutputStream(fileOutputStream);
Response 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**
```java
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 appOpensResponse = client.execute(appOpensRequest);
Response tiaResponse = client.execute(tiaRequest);
Response optInsResponse = client.execute(optInsRequest);
Response optOutsResponse = client.execute(optOutsRequest);
Response 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**
```java
PushInfoRequest request = PushInfoRequest.newRequest("ca15a452-ad5d-4bd9-95bb-e190eeba32cd");
Response 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 groupId = pushInfo.getGroupID();
```
Use the `PushInfoRequest.newRequst("")` class to get information on a particular push id.
### Response Listing
> Response Listing request:
**Get the response listing report**
```java
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 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**
```java
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**
```java
// 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 response = client.execute(customEventRequest);
```
To create a custom event, use the CustomEventRequest.newRequest() method:
# Airship PHP Library
> PHP library for using Airship's messaging platform and related features.## Resources
- [GitHub](https://github.com/urbanairship/php-library2/)
- [Packagist](https://packagist.org/packages/urbanairship/urbanairship)
- [Airship API Reference](https://www.airship.com/docs/developer/rest-api/ua/)
- [PHP Library API Reference](https://www.airship.com/docs/reference/libraries/php/latest)
> **Important:** Airship is no longer actively developing this library but will respond to feature requests, issues, and pull requests submitted to the [Airship Support site](https://support.airship.com). This library provides sample code, and Airship makes no guarantees as to completeness or regularity of updates.
## Requirements
- PHP >= 5.3
Dependencies
- Composer
- Httpful
- Monolog
- Development dependencies: PHPUnit
## Example usage
**Basic usage example**
```php
", "");
try {
$response = $airship->push()
->setAudience(P\iosChannel("Insert your iOS channel here!"))
->setNotification(P\notification("Hello from PHP"))
->setDeviceTypes(P\deviceTypes("ios"))
->send();
} catch (AirshipException $e) {
print_r($e);
}
```
# Airship Python Library
> Python library for using Airship's messaging platform and related features.## Resources
- [GitHub Repo](https://github.com/urbanairship/python-library/)
- [Python Package Index (PyPI)](https://pypi.python.org/pypi/urbanairship)
- [Airship API Reference](https://www.airship.com/docs/developer/rest-api/ua/)
- [Python Library API Reference](https://www.airship.com/docs/reference/libraries/python/latest)
## Installation
Using `pip`:
```bash
pip install urbanairship
```
## Using the library
The library is intended to be used with the small footprint of a single
import.
To get started, import the package, and create an `Airship` object representing a single Airship application:
```python
import urbanairship as ua
client = ua.BasicAuthClient('', '')
push = ua.Push(client)
push.audience = ua.ios_channel('074e84a2-9ed9-4eee-9ca4-cc597bfdbef3')
push.notification = ua.notification(ios=ua.ios(alert='Hello from Python', badge=1))
push.device_types = ua.device_types('ios')
push.send()
```
The library uses [Requests](https://requests.kennethreitz.org/en/master/) for communication with the Airship API,
providing connection pooling and strict SSL checking. The `Airship`
object is threadsafe and can be instantiated once and reused in multiple threads.
## Logging
`urbanairship` uses the standard logging module for integration into
an application's existing logging. If you do not have logging
configured otherwise, set it up in your application.
**Set up logging**
```python
import logging
logging.basicConfig()
```
If you're having trouble with the Airship API, you can turn on verbose debug
logging.
**Turn on verbose logging**
```python
logging.getLogger('urbanairship').setLevel(logging.DEBUG)
```
As of Python 2.7, `DeprecationWarning` warnings are silenced by
default. To enable them, use the `warnings` module.
**Turn on deprecation warnings**
```python
import warnings
warnings.simplefilter('default')
```
# Airship Ruby Library
> Ruby library for using Airship's messaging platform and related features.## Resources
- [GitHub Repo](https://github.com/urbanairship/ruby-library/)
- [rubygems.org](https://rubygems.org/gems/urbanairship/)
- [Airship API Reference](https://www.airship.com/docs/developer/rest-api/ua/)
- [Ruby Library API Reference](https://www.airship.com/docs/reference/libraries/ruby/latest)
## Installation
If you do not yet have the `bundler` gem, get it using:
**Install Bundler**
```bash
gem install bundler
```
Once you have the `bundler` gem, add this line to your application's
Gemfile:
**Install our gem**
```bash
gem 'urbanairship'
```
And then execute:
**Bundle**
```bash
bundle
```
Or install it yourself as:
**Alternative installation**
```bash
gem install urbanairship
```
## Configuration
In your app initialization, you can do something like the following:
**Example configuration**
```ruby
require 'urbanairship'
Urbanairship.configure do |config|
config.server = 'api.asnapieu.com'
config.oauth_server = 'oauth2.asnapieu.com'
config.log_path = '/path/to/your/logfile'
config.log_level = Logger::WARN
config.timeout = 60
end
```
If you want to use a custom logger such as Rails.logger, you can do:
**Custom logger**
```ruby
require 'urbanairship'
Urbanairship.configure do |config|
config.custom_logger = Rails.logger
config.log_level = Logger::WARN
end
```
### Available configurations
Allowances per configuration:
* log_path — Allows defining the folder where the log file will be created. The default is nil.
* log_level — Allows defining the log level. Only messages at that level or higher will be printed. The default is INFO.
* server — Allows defining the Airship server you want to use ("api.asnapieu.com" for EU or "api.asnapius.com" for US)
* oauth_server — Allows defining the Airship OAuth server you want to use. Use `oauth2.asnapieu.com` for EU or `oauth2.asnapius.com` for US.
* timeout — Allows defining the request timeout in seconds. The default is 5.
## Usage
Broadcast to all devices:
**Broadcast**
```ruby
require 'urbanairship'
UA = Urbanairship
airship = UA::Client.new(key:'application_key', secret:'master_secret')
p = airship.create_push
p.audience = UA.all
p.notification = UA.notification(alert: 'Hello')
p.device_types = UA.device_types(['ios','android'])
p.send_push
```
Basic tag push:
**Tag push**
```ruby
require 'urbanairship'
UA = Urbanairship
airship = UA::Client.new(key:'application_key', secret:'master_secret')
p = airship.create_push
p.audience = UA.tag('some_tag')
p.notification = UA.notification(alert: 'Hello')
p.device_types = UA.device_types(['ios','android'])
p.send_push
```
### Specify the Airship server used to make your requests
By default, the request will be sent to server api.asnapius.com:
**Default server with Basic auth**
```ruby
require 'urbanairship'
Urbanairship::Client.new(key:'application_key', secret:'master_secret')
```
You can change the server globally in the Urbanairship configuration:
**Using a different server**
```ruby
require 'urbanairship'
Urbanairship.configure do |config|
config.server = 'api.asnapieu.com'
end
Urbanairship::Client.new(key:'application_key', secret:'master_secret')
# request will be sent to the 'api.asnapieu.com' server
```
### Using Bearer Token auth
**Bearer token authentication**
```ruby
require 'urbanairship'
UA = Urbanairship
airship = UA::Client.new(key:'application_key', token:'token')
# Then continue as you would otherwise
```
### Using OAuth
**OAuth**
```ruby
require 'urbanairship'
UA = Urbanairship
app_key = 'application_key'
oauth = UA::Oauth.new(
client_id: 'client_id',
key: app_key,
assertion_private_key: 'your_private_key',
scopes: ['psh', 'chn'], # Optional
ip_addresses: ['23.74.131.15/22'], # Optional
oauth_server: 'api.asnapieu.com' # Optional
)
airship = UA::Client.new(key: app_key, oauth: oauth)
# Then continue as you would otherwise
```
> **Note:** * You cannot use both OAuth and Bearer Token auth at the same time.
> * OAuth cannot be used with the older `api.urbanairship.com` and `api.airship.eu` base URLs. See [Base URL](https://www.airship.com/docs/developer/rest-api/ua/introduction/#servers) and [OAuth](https://www.airship.com/docs/developer/rest-api/ua/operations/oauth/) in the *Airship API* reference.
> * OAuth is not supported for all endpoints. See the [Airship API Authorization Reference](https://www.airship.com/docs/developer/rest-api/ua/api-auth-reference/).