Removed deprecated APIs from 7.x.
Urban Airship now requires the minimum SDK version 16 (Jelly Bean).
Please update the build.gradle
file:
android {
defaultConfig {
minSdkVersion 16
}
}
The methods to report activity started and stopped have been removed.
// Removed
public static void activityStarted(Activity activity);
public static void activityStopped(Activity activity);
The GCM Instance ID and ADM ID retrieval methods have been consolidated into one generalized method.
// Old
UAirship.shared().getPushManager().getAdmId();
UAirship.shared().getPushManager().getGcmId();
// New
UAirship.shared().getPushManager().getRegistrationToken();
The LocalizableRemoteInput.Builder method setChoices(int[] choices)
has been removed and replaced with setChoices(int choices)
.
The notification factories have been refactored.
The SystemNotificationFactory
has been removed and replaced with the
NotificationFactory. The NotificationFactory
class now contains all
the setters from the default notification factory. The public notification, styles,
actions, and wearable notification setting have been moved into extender classes.
The CustomLayoutNotificationFactory constructor takes in a custom content view to display the notification. Custom binding can be applied by overriding [CustomLayoutNotificationFactory.onBindContentView](https://docs.urbanairship.com/reference/libraries/android/latest/reference/com/urbanairship/push/notifications/CustomLayoutNotificationFactory.html#onBindContentView(android.widget.RemoteViews, com/urbanairship/push/PushMessage, int)). To customize the builder, override [CustomLayoutNotificationFactory.extendBuilder](https://docs.urbanairship.com/reference/libraries/android/latest/reference/com/urbanairship/push/notifications/CustomLayoutNotificationFactory.html#extendBuilder(android.support.v4.app.NotificationCompat.Builder, com/urbanairship/push/PushMessage, int)).
The createNotification
method in DefaultNotificationFactory is now
final, thus please use the [DefaultNotificationFactory.extendBuilder](https://docs.urbanairship.com/reference/libraries/android/latest/reference/com/urbanairship/push/notifications/DefaultNotificationFactory.html#extendBuilder(android.support.v4.app.NotificationCompat.Builder, com/urbanairship/push/PushMessage, int)) method instead.
onChannelRegistrationSucceeded()
has been replaced by [AirshipReceiver.onChannelCreated](https://docs.urbanairship.com/reference/libraries/android/latest/reference/com/urbanairship/AirshipReceiver.html#onChannelCreated(android.content.Context, java.lang.String))
and [AirshipReceiver.onChannelUpdated](https://docs.urbanairship.com/reference/libraries/android/latest/reference/com/urbanairship/AirshipReceiver.html#onChannelUpdated(android.content.Context, java.lang.String)).
NamedUser access has been moved to UAirship.
// Old
UAirship.shared().getPushManager().getNamedUser()
// New
UAirship.shared().getNamedUser()
The internal GCM integration has been updated to not conflict with other integrations and no longer triggers the GcmListenerService when receiving GCM messages. Any application that contains additional GCM clients outside of Urban Airship needs to register the GcmReceiver from Google Play Services in the AndroidManifest.xml. The instructions provided in Set up a GCM Client App on Android can now be followed without adjustment.
BaseIntentReceiver
has been deprecated in favor of AirshipReceiver.
// Old inheritable methods
protected abstract void onChannelRegistrationSucceeded(@NonNull Context context, @NonNull String channelId);
protected abstract void onChannelRegistrationFailed(@NonNull Context context);
protected abstract void onPushReceived(@NonNull Context context, @NonNull PushMessage message, int notificationId);
protected abstract void onBackgroundPushReceived(@NonNull Context context, @NonNull PushMessage message);
protected abstract boolean onNotificationOpened(@NonNull Context context, @NonNull PushMessage message, int notificationId);
protected abstract boolean onNotificationActionOpened(@NonNull Context context, @NonNull PushMessage message, int notificationId, @NonNull String buttonId, boolean isForeground);
protected void onNotificationDismissed(@NonNull Context context, @NonNull PushMessage message, int notificationId) {}
// New inheritable methods
protected void onChannelRegistrationSucceeded(@NonNull Context context, @NonNull String channelId) {}
protected void onChannelRegistrationFailed(@NonNull Context context) {}
protected void onPushReceived(@NonNull Context context, @NonNull PushMessage message, boolean notificationPosted) {}
protected void onNotificationPosted(@NonNull Context context, @NonNull NotificationInfo notificationInfo) {}
protected boolean onNotificationOpened(@NonNull Context context, @NonNull NotificationInfo notificationInfo) {}
protected boolean onNotificationOpened(@NonNull Context context, @NonNull NotificationInfo notificationInfo, @NonNull notificationButtonInfo actionButtonInfo) {}
protected void onNotificationDismissed(@NonNull Context context, @NonNull NotificationInfo notificationInfo) {}
The method signatures have been simplified and now accept AirshipReceiver.NotificationInfo and AirshipReceiver.ActionButtonInfo objects instead of disparate fields. AirshipReceiver.NotificationInfo contains the relevant PushMessage and notification ID while AirshipReceiver.ActionButtonInfo contains fields pertinent to the notification action button.
onPushReceived()
and onBackgroundPushReceived
have been replaced by onPushReceived()
and onNotificationPosted()
.
onPushReceived()
now accepts a boolean flag indicating whether or not the notification will be in the foreground,
and onNotificationPosted()
will be called immediately after in the event that a notification is posted.
An Editor API is now provided for tag mutation operations.
// Old
Set<String> tags = new HashSet<String>();
tags = UAirship.shared().getPushManager().getTags();
tags.add("Some-Tag");
UAirship.shared().getPushManager().setTags(tags);
// New
UAirship.shared().getPushManager().editTags()
.addTag("some_tag")
.removeTag("some_other_tag")
.apply();
An Editor API is now provided for associated identifier mutation operations replacing the
deprecated associateIdentifiers
method. Use Analytics.editAssociatedIdentifiers.
// Old
AssociatedIdentifiers.Builder identifiers = new AssociatedIdentifiers.Builder()
.setIdentifier("customIdentifierKey", "customIdentifierValue")
.create();
UAirship.shared().getAnalytics().associateIdentifiers(identifiers);
// New
UAirship.shared().getAnalytics()
.editAssociatedIdentifiers()
.addIdentifier("customIdentifierKey", "customIdentifierValue")
.apply();
AirshipConfigOptions is no longer mutable after being created. All the public fields are now final and can only be
set using the new AirshipConfigOptions.Builder
class. This only affects classes that programmatically set the config.
// Old
AirshipConfigOptions options = new AirshipConfigOptions();
options.inProduction = false;
options.developmentAppKey = "Your Development App Key";
options.developmentAppSecret "Your Development App Secret";
// New
AirshipConfigOptions options = new AirshipConfigOptions.Builder()
.setInProduction(false)
.setDevelopmentAppkey("Your Development App Key")
.setDevelopmentAppSecret("Your Development App Secret")
.build();
A Message Center is now included with the SDK. Applications that have built a custom Message Center are still supported, but need to implement support for Displaying the Message Center to override the SDK's Message Center.
The Message Center can be displayed with:
UAirship.shared().getInbox().showInboxActivity();
The inbox listener method onUpdateInbox
has been renamed to onInboxUpdated
:
// Old
public interface Listener {
void onUpdateInbox();
}
// New
public interface Listener {
/**
* Called when the inbox is updated.
*/
void onInboxUpdated();
}
The inbox can now be accessed directly from UAirship:
// Old
RichPushInbox inbox = UAirship.shared().getRichPushManager().getRichPushInbox();
// New
RichPushInbox inbox = UAirship.shared().getInbox();
The inbox user accessor has moved to RichPushInbox:
// Old
RichPushUser user = UAirship.shared().getRichPushManager().getRichPushUser();
// New
RichPushUser user = UAirship.shared().getInbox().getUser();
Forcing a message list update has also moved to the RichPushInbox.
// Old
RichPushUser user = UAirship.shared().getRichPushManager().refreshMessages();
// New
Cancelable cancelable = UAirship.shared().getInbox().fetchMessages();
A listener for fetch message requests has been removed. Instead, provide a callback when fetching messages:
Cancellable cancellable = UAirship.shared().getInbox().fetchMessages(new RichPushInbox.FetchMessagesCallback() {
@Override
public void onFinished(boolean success) {
// message request complete
}
});
A function that checked whether a message was a Rich Message has been removed. You can identify a message as a Rich Message by checking if the Rich Push Message ID is not null.
boolean isRichPushMessage = !TextUtils.isEmpty(message.getRichPushMessageId());
The signature of requestSingleLocation changed to now accept an optional LocationCallback and return a Cancelable instance instead of a PendingResult.
// Old
public PendingResult<Location> requestSingleLocation(@NonNull LocationRequestOptions requestOptions);
public PendingResult<Location> requestSingleLocation();
// New
public Cancelable requestSingleLocation(@Nullable LocationCallback locationCallback, @NonNull LocationRequestOptions requestOptions);
public Cancelable requestSingleLocation(@Nullable LocationCallback locationCallback);
public Cancelable requestSingleLocation();
LocationEvent now uses static constants instead of the UpdateType enum.
// Old
public enum UpdateType {
CONTINUOUS,
SINGLE
}
// New
public final static int UPDATE_TYPE_CONTINUOUS = 0;
public final static int UPDATE_TYPE_SINGLE = 1;
Action now uses static constants instead of the Situation enum.
// Old
public enum Situation {
MANUAL_INVOCATION,
PUSH_RECEIVED,
PUSH_OPENED,
WEB_VIEW_INVOCATION,
FOREGROUND_NOTIFICATION_ACTION_BUTTON,
BACKGROUND_NOTIFICATION_ACTION_BUTTON
}
// New
public final static int SITUATION_MANUAL_INVOCATION = 0;
public final static int SITUATION_PUSH_RECEIVED = 1;
public final static int SITUATION_PUSH_OPENED = 2;
public final static int SITUATION_WEB_VIEW_INVOCATION = 3;
public final static int SITUATION_FOREGROUND_NOTIFICATION_ACTION_BUTTON = 4;
public final static int SITUATION_BACKGROUND_NOTIFICATION_ACTION_BUTTON = 5;
ActionResult now uses static constants instead of the Status enum.
// Old
public enum Status {
COMPLETED,
REJECTED_ARGUMENTS,
ACTION_NOT_FOUND,
EXECUTION_ERROR
}
// New
public static final int STATUS_COMPLETED = 1;
public static final int STATUS_REJECTED_ARGUMENTS = 2;
public static final int STATUS_ACTION_NOT_FOUND = 3;
public static final int STATUS_EXECUTION_ERROR = 4;
NotificationIDGenerator
has been renamed to NotificationIdGenerator
.
Added AndroidManifest.xml for automatic manifest merging. Existing integrations
will be required to remove Urban Airship manifest entries from their AndroidManifest.xml and
applications must define applicationId
in the project's build.gradle
file.
See merge conflict docs
for details on overriding manifest entries.
GCM registration now uses Instance ID tokens instead of registration IDs. Urban Airship
SDK will continue to register all sender IDs, but this has been deprecated and will be removed
in 7.0.0. Applications that use additionalSenderIds
should now register directly with
GCM.
As of Android SDK 7.2.0, our registration no longer conflicts with other providers. Upgrade to minimum version 7.2.0 if you are using additional sender IDs.
The updateUser()
and updateUserIfNecessary()
methods have been deprecated and
marked to be removed in 7.0.0. Use updateUser(boolean)
instead.
// Deprecated method
public void updateUser();
public void updateUserIfNecessary();
// Added method
public void updateUser(boolean forcefully) ;
The isFusedLocationDepdendencyAvailable()
method has been deprecated and marked
to be removed in 7.0.0. It has been replaced with isFusedLocationDependencyAvailable()
.
// Deprecated method
public static boolean isFusedLocationDepdendencyAvailable()
// Added method
public static boolean isFusedLocationDependencyAvailable()
Urban Airship now requires the minimum SDK version 8 (Froyo).
For Android Studio/Gradle projects, update the build.gradle
file:
android {
defaultConfig {
minSdkVersion 8
}
}
If using Eclipse, you can set the minSdkVersion
in the AndroidManifest.xml
file:
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="22" />
LandingPageWebView and RichPushMessageWebView have been deprecated and all functionality has been merged into UAWebView. Replace any usages of the deprecated web views with the UAWebView.
The landing page activity is now able to display Rich Push Messages. Update the AndroidManifest.xml entry to add "message" scheme for the intent filter:
<activity
android:name="com.urbanairship.actions.LandingPageActivity"
android:exported="false">
<intent-filter>
<action android:name="com.urbanairship.actions.SHOW_LANDING_PAGE_INTENT_ACTION" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:scheme="message" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
For custom landing page activities, the message ID can be accessed through the intent's data:
Uri uri = intent.getData();
if (uri.getScheme().equalsIgnoreCase(RichPushInbox.MESSAGE_DATA_SCHEME)) {
String messageId = uri.getSchemeSpecificPart();
RichPushMessage message = UAirship.shared()
.getRichPushManager()
.getRichPushInbox()
.getMessage(messageId);
if (message != null) {
uaWebView.loadRichPushMessage(message);
message.markRead();
} else {
// message not found
}
}
When a push message is opened that references a Rich Push Message, the OpenRichPushInboxAction
will automatically be triggered. The action will attempt to automatically deep link to an activity by starting
an intent with action com.urbanairship.VIEW_RICH_PUSH_MESSAGE
to view the message. If the intent fails
to start an activity, the action will now default to displaying the message in the landing page activity.
Applications should either remove custom deep linking code for Rich Push Messages and implement support for Displaying the Message Center, or they should override OpenRichPushInboxAction.
The setter and getter for deviceTagsEnabled
has been deprecated and replaced
with channelTagRegistrationEnabled
.
// Deprecated
public boolean getDeviceTagsEnabled();
public void setDeviceTagsEnabled(boolean enabled);
// Added
public boolean getChannelTagRegistrationEnabled();
public void setChannelTagRegistrationEnabled(boolean enabled);
It is recommended to use the v7 CardView support library for in-app messaging to provide a consistent style across all devices.
Using Android Studio:
dependencies {
`com.android.support:cardview-v7:22.0.0`
...
}
Eclipse users should follow Android Developer docs.
The action's registry name has been removed from any action methods. The action name is now part of the action argument's metadata.
Example:
@Override
public void onStart(ActionArguments arguments) {
// Called before perform
}
@Override
public ActionResult perform(ActionArguments arguments) {
String actionName = arguments.getMetadata()
.getString(ActionArguments.REGISTRY_ACTION_NAME_METADATA);
...
}
@Override
public void onFinish(ActionArguments arguments, ActionResult result) {
// Called after perform
}
ActionRunner
has been replaced with a new ActionRunRequest
class that provides a fluent API
for running actions. The action run request takes in a value, situation, and metadata and constructs
the ActionArgument
and passes it to the action to run.
Example:
// Run the action "actionName" with value "actionValue"
ActionRunRequest.createRequest("actionName")
.setSituation(Situation.MANUAL_INVOCATION)
.setValue("actionValue")
.run();
The action registry is no longer a singleton and shared
has been deprecated. The default registry can be accessed through UAirship
.
Example:
ActionRegistry registry = UAirship.shared().getActionRegistry();
Action arguments creation is no longer visible, and instead will be created by ActionRunRequest
and
passed to the action.
Argument's value can now only contain an ActionValue
instance. ActionValue
is a new class that limits the type of values to those that can be JSON serializable. The ActionValue
class contains getter methods
that automatically does type checking to parse value back into its original form.
Example:
Action logAction = new Action() {
@Override
public ActionResult perform(ActionArguments arguments) {
Log.i("TestAction", arguments.getValue().getString());
return ActionResult.newResult(arguments.getValue());
}
};
// Log "hello"
ActionRunRequest.createRequest(logAction)
.setValue("hello")
.run();
Argument's metadata is now stored and accessed through a Bundle
. RichPushMessages
are no longer available as metadata, instead the message's ID will be made available under the key RICH_PUSH_ID_METADATA
.
Changes:
// Added methods
Bundle getMetadata();
ActionValue getValue();
// Added fields
public static final String RICH_PUSH_ID_METADATA;
// Removed constructor
ActionArguments(Situation situation, Object value);
// Removed methods
<T> T getMetadata(String key);
Object getValue();
// Removed fields
public static final String RICH_PUSH_METADATA;
// Removed class
public class Builder;
Action results are now restricted to an ActionValue
for the result's value.
The action completion callback now calls onFinish
with both the ActionArguments
and ActionResult
.
Changes:
// Added methods
public void onFinish(ActionArguments arguments, ActionResult result);
// Removed
public void onFinish(ActionResult result);
We introduced two intents that will allow deep linking for in-app messaging. See Displaying the Message Center for more details.
AutoPilot no longer defines and calls execute
. Instead, classes that implement AutoPilot are expected
to implement the interface OnReadyCallback
to perform any setup after take off is complete. Optionally
AutoPilot classes can override createAirshipConfigOptions
to provide custom config.
Example:
public class ExampleAutoPilot extends Autopilot {
@Override
public AirshipConfigOptions createAirshipConfigOptions(Context context) {
// Optionally return takeoff custom take off options or null
// to asynchronously create the config from airshipconfig.properties
return null;
}
@Override
public void onAirshipReady(UAirship airship) {
// Perform any airship setup here
airship.getPushManager().setUserNotificationsEnabled(true);
}
}
Major highlights of this release:
-
Android Lollipop notification support.
-
Advanced notification support through the Push API, including support for Android Wear and styles. See Android Push API for more details.
-
Enhanced security when using the Urban Airship JavaScript bridge in custom web view implementations.
The SDK now requires the latest Google Play Services (6.1 or greater) for Android and the latest support v4 library (revision 21 or greater). Gradle 0.13.3+ is required for Android Studio.
To target and support the latest features in Android Lollipop, the Urban Airship SDK is now built with JDK 7. When using Android Studio, you may need to update the JDK location to point to JDK 7 in file -> project settings -> SDK Location -> JDK Location.
The Urban Airship JavaScript bridge is now only injected in the UAWebViewClient if the URL is whitelisted. Urban Airship URLs are automatically whitelisted, but if the UA JavaScript bridge is used outside of Urban Airship hosted Rich Application Pages, the hosting urls need to be whitelisted.
Whitelists rules can be defined in the airshipconfig.properties file:
whitelist = *://*.mydomain.com, file:///android-asset/*
Whitelist rules can also be defined directly:
airship.getWhitelist().addEntry("https://*.urbanairship.com");
See Whitelist for more details on creating valid url patterns.
Major highlights of this release:
-
The Airship Push Identifier (APID) has been replaced with the Channel Identifier (Channel ID). Existing APIDs will automatically migrate to Channel IDs. A channel will always be created and available. When push is disabled, instead of deleting the APID the channel will be updated to opted-out, allowing the device to remain addressable for other services, e.g., Rich App Pages.
-
A new Location module that supports Google Play Services' Fused Location Provider when available.
-
This library supports both Amazon Device Messaging (ADM) and Google Cloud Messaging (GCM).
For the last few versions we focused on providing a stable API. Given the major improvements added in this release, it was necessary to redesign portions of the library.
The Urban Airship library is now a library project with resources. Eclipse users
will import the library as a project and reference it. The library is
packaged as an aar
file for Android Studio users. More details can be found in
Android: Getting Started.
The Urban Airship SDK now depends on Google Play Services for GCM registration. The library is built against Google Play Services, but does not package it for applications. Instead, any application that wants to support GCM needs to include Google Play Services as a dependency. Set up instructions can be found here.
Urban Airship provides utility classes to simplify Google Play Services error handling.
AndroidManifest.xml changes:
<!-- REQUIRED for PlayServiceUtils.handleAnyPlayServicesError to handle Google Play Services recoverable errors. -->
<activity android:name="com.urbanairship.google.PlayServicesErrorActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" />
Add this call to your main activity's onStart method:
// Handle any Google Play Services errors
if (PlayServicesUtils.isGooglePlayStoreAvailable()) {
PlayServicesUtils.handleAnyPlayServicesError(this);
}
This will automatically start a transparent activity that checks for Google Play service errors. If any user recoverable errors are detected, the activity will show an error dialog to the user to resolve the issue.
Calling takeOff()
is now asynchronous. Calling shared() now blocks the first time
until airship is ready. A new shared method with a callback is now available to
prevent blocking the main thread.
Example:
// Calling takeOff() with a callback
UAirship.takeOff(this, new UAirship.OnReadyCallback() {
@Override
public void onAirshipReady(UAirship airship) {
airship.getPushManager().setPushEnabled(true);
}
});
// Getting the UAirship instance asynchronously
UAirship.shared(new UAirship.OnReadyCallback() {
@Override
public void onAirshipReady(UAirship airship) {
airship.getPushManager().setPushEnabled(true);
}
});
// Getting the UAirship instance synchronously
UAirship airship = UAirship.shared();
// Checking if UAirship is ready
if (UAirship.isReady()) {
// Airship is ready, shared() no longer blocks
}
The shared method on PushManager, RichPushManager, and LocationManager have been deprecated and replaced with getters on the shared UAirship instance:
// Deprecated
PushManager.shared();
RichPushManager.shared();
LocationManager.shared();
// Added
UAirship.shared().getPushManager();
UAirship.shared().getRichPushManager();
UAirship.shared().getLocationManager();
The core receiver now depends on an intent filter and a priority being set, update the entry with the following:
<!-- REQUIRED for Urban Airship Push. The priority is important to be set lower than the
application's push intent receiver in order for the push intent receiver to handle push intents
before the core receiver. This allows the application to launch any activities before Urban
Airship performs any actions or falls back to launching the application launch intent. -->
<receiver android:name="com.urbanairship.CoreReceiver"
android:exported="false">
<intent-filter android:priority="-999">
<action android:name="com.urbanairship.push.OPENED" />
<!-- MODIFICATION REQUIRED - Use your package name as the category -->
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
A new core activity is now required for notification action buttons. Add the following under the application entry:
<activity android:name="com.urbanairship.CoreActivity"/>
The richPushEnabled
and pushServiceEnabled
fields have been removed, thus Rich
Push and Push will now be initialized by default. The transport field is no longer
used. ADM and GCM will automatically be selected based on the detected platform.
The following changes have been made for AirshipConfigOptions:
// Removed fields
public String transport;
public boolean richPushEnabled;
public boolean pushServiceEnabled;
// Added fields
public long backgroundReportingIntervalMS;
// Removed methods
public TransportType getTransport();
Push registration intents have been updated for channels and notification action buttons. A new abstract broadcast receiver 'BaseIntentReceiver' is now available that can be extended to make parsing the intents easier.
public class IntentReceiver extends BaseIntentReceiver {
private static final String TAG = "IntentReceiver";
@Override
protected void onChannelRegistrationSucceeded(Context context, String channelId) {
Log.i(TAG, "Channel registration updated. Channel Id:" + channelId + ".");
}
@Override
protected void onChannelRegistrationFailed(Context context) {
Log.i(TAG, "Channel registration failed.");
}
@Override
protected void onPushReceived(Context context, PushMessage message, int notificationId) {
Log.i(TAG, "Received push notification. Alert: " + message.getAlert() + ". Notification ID: " + notificationId);
}
@Override
protected void onBackgroundPushReceived(Context context, PushMessage message) {
Log.i(TAG, "Received background push message: " + message);
}
@Override
protected boolean onNotificationOpened(Context context, PushMessage message, int notificationId) {
Log.i(TAG, "User clicked notification. Alert: " + message.getAlert());
return false;
}
@Override
protected boolean onNotificationActionOpened(Context context, PushMessage message, int notificationId, String buttonId, boolean isForeground) {
Log.i(TAG, "User clicked notification button. Button ID: " + buttonId + " Alert: " + message.getAlert());
return false;
}
}
The intent receiver is no longer set directly on PushManager. Instead, set an intent filter in the receiver's intent filter.
<!-- OPTIONAL, if you want to receive push, push opened and registration completed intents -->
<!-- Replace the receiver below with your package and class name -->
<receiver android:name="com.urbanairship.push.sample.IntentReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.urbanairship.push.CHANNEL_UPDATED" />
<action android:name="com.urbanairship.push.OPENED" />
<action android:name="com.urbanairship.push.RECEIVED" />
<!-- MODIFICATION REQUIRED - Use your package name as the category -->
<category android:name="com.urbanairship.push.sample" />
</intent-filter>
</receiver>
It is no longer necessary to set an intent receiver to only launch the application when a notification is opened. Instead, the library supports launching the application's launch intent if the application does not handle the intent or does not launch an activity from the notification open broadcasts.
The intent receiver no longer needs to check for Urban Airship Action when determining if the application needs to be launched. Actions now run after the application is launched.
It is now possible to turn off just user notifications in order to send data-only messages to the application when the user is opted out of notifications. User notifications defaults to false, and push enabled now defaults to true. The previous push enabled setting is automatically migrated to the new user notification setting.
// Removed methods
public static void enablePush();
public static void disablePush();
// Added method
public void setPushEnabled(boolean enabled);
public boolean isPushEnabled();
public void setUserNotificationsEnabled(boolean enabled);
public boolean getUserNotificationsEnabled();
Since APIDs have been replaced with channels, the getAPID()
method has been
removed and replaced by getChannelId()
.
// Removed method
public String getAPID();
// Added method
public String getChannelId();
The getPreferences()
method and PushPreferences have been removed. Please use
the preference getters and setters on PushManager instead:
// Removed method
public PushPreferences getPreferences();
// Added methods
public boolean isPushEnabled();
public boolean isSoundEnabled();
public void setSoundEnabled(boolean enabled);
public boolean isVibrateEnabled();
public void setVibrateEnabled(boolean enabled);
public boolean isQuietTimeEnabled();
public void setQuietTimeEnabled(boolean enabled);
public boolean isInQuietTime();
public Date[] getQuietTimeInterval();
public String getLastReceivedSendId();
public void setQuietTimeInterval(Date startTime, Date endTime);
PushNotificationBuilder, BasicPushNotificationBuilder, and CustomPushNotificationBuilder have been removed with a new properly named classes NotificationFactory, SystemNotificationFactory, and CustomLayoutNotificationFactory.
A new factory, DefaultNotificationFactory, is now the default and automatically applies big text style to all notifications. The SystemNotificationFactory can be used instead if the big text style is undesirable:
final SystemNotificationFactory notificationFactory = new SystemNotificationFactory(this);
UAirship.takeOff(this, new UAirship.OnReadyCallback() {
@Override
public void onAirshipReady(UAirship airship) {
airship.getPushManager().setNotificationFactory(notificationFactory);
}
});
Custom notification factories are still supported, but they need to now extend NotificationFactory base class.
Example:
public class CustomNotificationFactory extends NotificationFactory {
public CustomNotificationFactory(Context context) {
super(context);
}
@Override
public Notification createNotification(PushMessage message, int notificationId) {
// Build the notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(getContext())
.setContentTitle("Notification title")
.setContentText(message.getAlert())
.setAutoCancel(true)
.setSmallIcon(R.drawable.notification_icon);
// To support interactive notification buttons, extend the NotificationCompat.Builder
builder.extend(createNotificationActionsExtender(message, notificationId));
return builder.build();
}
@Override
public int getNextId(PushMessage pushMessage) {
return NotificationIDGenerator.nextID();
}
}
The methods to report activity started and stopped are now static. This is to prevent blocking on the shared UAirship instance when reporting the activity state.
// Removed
public void activityStarted(Activity activity);
public void activityStopped(Activity activity);
// Added
public static void activityStarted(Activity activity);
public static void activityStopped(Activity activity);
APID and Location preferences have been updated for channels and the new location module:
// Removed classes
public class ApidPreference;
public class LocationEnablePreference;
public class LocationForegroundEnablePreference;
public class LocationBackgroundEnablePreference;
// Added classes
public class ChannelIdPreference;
public class LocationUpdatesEnabledPreference;
public class LocationBackgroundUpdatesAllowedPreference;
The getRichPushInbox()
has been added to get the RichPushInbox:
// Added method
public synchronized RichPushInbox getRichPushInbox();
The RichPushInbox shared()
method has been deprecated. Please use
RichPushManager's getRichPushInbox()
method instead:
// Deprecated method
public synchronized static RichPushInbox shared();
The getInbox()
method has been deprecated. Please use RichPushManager's
getRichPushInbox()
method instead:
// Deprecated method
public synchronized RichPushInbox getInbox();
With the removal of APIDs, the APID related methods have been removed:
// Removed methods
public void setApids(HashSet<String> apids);
public void addApid(String apid);
public HashSet<String> getApids();
The GCMMessageHandler
have been removed. All GCM constants are now located in
GCMConstants
.
The new location module has been completely rewritten in the Urban Airship SDK and is now compatible with Google Play Services' Fused Location Provider. Fused Location will automatically be used if Google Play Services is available on the device, is up to date, and the application was built with the Google Play Services dependency.
LocationOptions, including locationServiceEnabled
, is no longer used for
Location and have been removed. The backgroundReportingIntervalSeconds
field
has been renamed to backgroundReportingIntervalMS
and moved to
AirshipConfigOptions.
Location requests options are modeled after the Fused Location Provider by specifying high level needs instead of low level criteria. The location request options will automatically be converted to either criteria when using the standard Android Location APIs or to a LocationRequest when using Fused Location Provider.
LocationRequestOptions options = new LocationRequestOptions.Builder()
.setPriority(LocationRequestOptions.PRIORITY_BALANCED_POWER_ACCURACY)
.setMinDistance(800)
.setMinTime(5, TimeUnit.MINUTES)
.create();
// Set the default continuous location request options
UAirship.shared().getLocationManager().setLocationRequestOptions(options);
The settings for enabling location have been simplified. Location updates are
enabled or disabled by setLocationUpdatesEnabled()
. Updates continuing in the
background is controlled by setBackgroundLocationAllowed()
. Listening for
background locations now requires both location updates enabled and background
location allowed.
Changes in UALocationManager
:
// Removed methods
public static void enableLocation();
public static void disableLocation();
public static void enableBackgroundLocation();
public static void enableForegroundLocation();
public static void disableForegroundLocation();
public static void disableBackgroundLocation();
public LocationPreferences getPreferences();
// Added methods
public boolean isLocationUpdatesEnabled();
public void setLocationUpdatesEnabled(boolean enabled);
public boolean isBackgroundLocationAllowed();
public void setBackgroundLocationAllowed(boolean enabled);
Listening for location updates is still supported but updates will no longer be sent as a broadcast to a BroadcastReceiver. Instead, a location listener can be added to UALocationManager to listen for continuous location updates.
Changes in UALocationManager
:
// Removed methods
public void setIntentReceiver(Class<? extends BroadcastReceiver> receiver);
public Class<? extends BroadcastReceiver> getIntentReceiver();
// Added methods
public void addLocationListener(LocationListener listener);
public void removeLocationListener(LocationListener listener);
Example:
LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.i(TAG, "Received location: " + location);
}
};
// Listening for updates
UAirship.shared().getLocationManager().addLocationListener(locationListener);
...
// Stop listening for updates when finished
UAirship.shared().getLocationManager().removeLocationListener(locationListener);
Single location requests can be made at any time without checking if the service is bound or not. Binding and unbinding to the location service is handled internally in the UALocationManager. A pending result will be returned when requesting a single location, which allows canceling the request and allows setting a callback when the location is ready.
Changes in UALocationManager
:
// Removed methods
public void recordCurrentLocation();
public void recordCurrentLocation(Criteria criteria);
public static boolean isServiceBound();
public static void bindService();
public static void unbindService();
// Added methods
public PendingResult requestSingleLocation();
public PendingResult requestSingleLocation(LocationRequestOptions requestOptions);
Example:
UALocationManager locationManager = UAirship.shared().getLocationManager();
// Request a single location with the current location request options
PendingResult<Location> pendingRequest = locationManager.requestSingleLocation();
// Optionally, specify the location request options
// PendingResult<Location> pendingRequest = locationManager.requestSingleLocation(customRequestOptions);
// Add a callback for when the location is ready
pendingRequest.onResult(new PendingResult.ResultCallback<Location>() {
@Override
public void onResult(Location result) {
Log.i(TAG, "New location: " + result);
}
});
...
// Optionally, cancel the request
pendingRequest.cancel();
The methods for uploading location events through the UALocationManager
have
been removed and replaced with Urban Airship Analytics' method recordLocation()
.
Changes in UALocationManager
:
// Removed methods
public void recordLocation(Location newLocation);
public void recordLocation(Location newLocation, int accuracy, int minDistance);
When a new location becomes available, record the location:
UAirship.shared().getAnalytics().recordLocation(location);
The location will be automatically batched and uploaded.
Migration is only needed if your application is listening for location updates from the UALocationManager. Location updates will no longer be broadcasted to the entire system with an implicit intent, instead they will be broadcasted to only the receiver that is set on UALocationManager.
The following changes have been made to UALocationManager because it is no longer necessary to namespace the location broadcasts:
// Removed constants
public static final String ACTION_SUFFIX_LOCATION_UPDATE;
public static final String ACTION_SUFFIX_LOCATION_SERVICE_BOUND;
public static final String ACTION_SUFFIX_LOCATION_SERVICE_UNBOUND;
// Removed method
public static String getLocationIntentAction(final String suffix);
// Added constants
public static final String ACTION_LOCATION_UPDATE;
public static final String ACTION_LOCATION_SERVICE_BOUND;
public static final String ACTION_LOCATION_SERVICE_UNBOUND;
// Added methods
public Class<? extends BroadcastReceiver> getIntentReceiver();
public void setIntentReceiver(Class<? extends BroadcastReceiver> receiver);
Application code and design changes can be minimized by using the LocalBroadcastManager from the Android Support Library to securely broadcast location to the entire application.
Example
Create an intent receiver that locally broadcasts location intents:
public class LocationIntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
}
Set the intent receiver after takeoff:
UAirship.takeOff(this);
UALocationManager.shared().setIntentReceiver(LocationIntentReceiver.class);
Add the intent receiver in the AndroidManifest.xml under the application element:
<receiver android:name=".LocationIntentReceiver" />
Register existing receivers using the LocalBroadcastReceiver:
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, intentFilter);
This release adds support for Urban Airship Actions. In order to use Actions, you must make a few changes
to AndroidManifest.xml
and possibly the PushReceiver
that handles push notifications.
See Android Actions for more information on Actions.
The namespace urbanairship
has been deprecated and replaced with UAirship
which
is consistent between both iOS and Android.
RichPushMessageJavascriptInterface
and RichPushMessageJavascript
have been replaced
by com.urbanairship.js.UAJavascriptInterface
.
Support for these deprecated features will be removed after October 2, 2014.
RichPushManager
no longer allows setting a custom JavaScript interface and namespace.
This only affects apps that are using Rich App Pages that use JavaScript
with a custom namespace or a customized interface. Custom JavaScript Interfaces are still
supported but are encouraged to be used under a different namespace.
To add custom interfaces, create a new class that extends RichPushMessageWebView
and override the
populateCustomJavascriptInterfaces
method.
Example:
public class CustomRichPushMessageWebView extends RichPushMessageWebView {
public CustomRichPushMessageWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomRichPushMessageWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomRichPushMessageWebView(Context context) {
super(context);
}
@Override
protected void populateCustomJavascriptInterfaces() {
addJavascriptInterface(new CustomJavascriptInterface(), "CustomNameSpace");
}
class CustomJavascriptInterface {
@JavascriptInterface
public String myMethod() {
return "hello";
}
}
}
If a customized version of the Urban Airship JavaScript Interface is required to be used under
the urbanairship
namespace, create a new class that extends RichPushMessageWebView
and override
the loadUrbanAirshipJavascriptInterface
method. Make sure to still load the unmodified version
of the RichPushMessageJavascriptInterface
under the UAirship
namespace in order to use actions
through JavaScript.
public class CustomRichPushMessageWebView extends RichPushMessageWebView {
public CustomRichPushMessageWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomRichPushMessageWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomRichPushMessageWebView(Context context) {
super(context);
}
@Override
protected void populateCustomJavascriptInterfaces() {
// Add any custom JavaScript interfaces. The interfaces will be called
// when RichPushMessageWebView is constructed.
addJavascriptInterface(new CustomJavascriptInterface(), "CustomNameSpace");
}
@Override
protected void loadJavascriptInterface(RichPushMessage message) {
// Load unmodified version of the UAJavascriptInterface
UAJavascriptInterface js = new UAJavascriptInterface(this, message);
addJavascriptInterface(js, UAJavascriptInterface.JAVASCRIPT_IDENTIFIER);
// Load the extended version of the interface under the "uairship" namespace
CustomJavascriptInterface js = new CustomUAJavascriptInterface(this, message);
addJavascriptInterface(js, UAJavascriptInterface.DEPRECATED_JAVASCRIPT_IDENTIFIER);
}
public static class CustomUAJavascriptInterface extends UAJavascriptInterface {
public CustomJavascriptInterface(WebView webView, RichPushMessage message) {
super(webView, message);
}
// Do any customizations
}
public static class CustomJavascriptInterface {
@JavascriptInterface
public String myMethod() {
return "hello";
}
}
}
Update any uses of RichPushMessageWebView
to CustomRichPushMessageWebView
so the custom
JavaScript interfaces are used.
RichPushMessageView
has been renamed RichPushMessageWebView
. When setting
a custom web view client on the view, the client should extend the UAWebViewClient
and any methods that are overridden should call through to the super class implementations.
RichPushManager.Listener no longer defines public void onRetrieveMessage(boolean success, String messageId). The callback was used for internal purposes only and is no longer needed. If any class implements this callback, it is safe to just remove it.
The batch operations for marking messages read, marking messages unread, and deleting messages no longer block on database operations, but they also no longer return the number of items successfully changed.
// Old calls that returned an int
public int markMessagesRead(final Set<String> messageIds)
public int markMessagesUnread(final Set<String> messageIds)
public int deleteMessages(final Set<String> messageIds)
// New calls that return void
public void markMessagesRead(final Set<String> messageIds)
public void markMessagesUnread(final Set<String> messageIds)
public void deleteMessages(final Set<String> messageIds)
Helium and Hybrid transport type is no longer supported. Please use GCM instead GCM Setup.
Part of some internal restructuring, the following constants have moved:
GCMMessageHandler.ACTION_GCM_RECEIVE // moved from PushManager.ACTION_GCM_RECEIVE
GCMMessageHandler.ACTION_GCM_DELETED_MESSAGES // moved from PushManager.ACTION_GCM_DELETED_MESSAGES
GCMMessageHandler.EXTRA_GCM_MESSAGE_TYPE // moved from PushManager.EXTRA_GCM_MESSAGE_TYPE
GCMMessageHandler.EXTRA_GCM_TOTAL_DELETED // moved from PushManager.EXTRA_GCM_TOTAL_DELETED
GCMMessageHandler.GCM_DELETED_MESSAGES_VALUE // moved from PushManager.GCM_DELETED_MESSAGES_VALUE
GCMRegistrar.EXTRA_GCM_REGISTRATION_ID // moved from PushManager.EXTRA_GCM_REGISTRATION_ID
RichPushInbox no longer extends the Cursor interface. It is no longer required to use a cursor adapter, instead use a list adapter. A full example can be found here Android Message Center.
Push Worker Service is no longer used and needs to be removed from the AndroidManifest.xml.
Remove this line from the AndroidManifest.xml file:
<service android:name="com.urbanairship.push.PushWorkerService" android:label="Push Notification Worker Service"/>