In-App Messaging for Android

Note

This guide applies to in-app messages sent via In-App Automation.

In-app messaging can improve your engagement strategy by providing messages that can be customized to be visually consistent with the the rest of your app. Most customization can be accomplished through the dashboard workflow, however more advanced customization can be obtained by modifying the Urban Airship SDK. This guide outlines how to customize Android in-app messages.

Feature enablement

Disabling the manager:

UAirship.shared()
        .getInAppMessagingManager()
        .setEnabled(false);

The in-app messaging manager can be enabled or disabled. When the manager is disabled it prevents any in-app messages from displaying and pausing the automation engine counting. The manager is enabled by default.

Display interval

Setting the display interval to 10 seconds:

UAirship.shared()
        .getInAppMessagingManager()
        .setDisplayInterval(10, TimeUnit.SECONDS);

The display interval controls the amount of time to wait before the manager is able to display the next triggered in-app message. The default value is set to 30 seconds but can be adjusted to any amount of time.

Listening for events

Example listener:

UAirship.shared()
        .getInAppMessagingManager()
        .addListener(new InAppMessageListener() {
            @Override
            public void onMessageDisplayed(@NonNull String scheduleId, @NonNull InAppMessage message) {
                // Message displayed
            }

            @Override
            public void onMessageFinished(@NonNull String scheduleId, @NonNull InAppMessage message, @NonNull ResolutionInfo resolutionInfo) {
                // Message finished
            }
        });

A listener can be added to the in-app messaging manager to listen for when a message is displayed and finished displaying. This is useful for adding analytics events outside of Urban Airship as well as for further processing of the in-app message.

Fonts

Fonts that are added in XML are available for use with in-app messaging, including downloadable fonts. To add fonts, please read the Fonts In XML guide. Once added, you can specify the fonts by using the resource name, e.g., use cool_font for res/xml/cool_font.xml.

Excluding Activities

Exclude activity from displaying in-app messages:

<meta-data
      android:name="com.urbanairship.push.iam.EXCLUDE_FROM_AUTO_SHOW"
      android:value="true" />

Activities can be excluded from auto-displaying an in-app message. This is useful for preventing in-app message displays on screens where it would be detrimental for the user experience, such as splash screens, settings screens, or landing pages.

Customization

In-app messages are fully customizable. Minor modifications can be accomplished by overriding the styles, but more advanced customizations can employ an adapter for the given message type.

Styles

The Android resource merging feature can be used to override any of the message styles that the SDK provides. Copy any of the styles that need to be overridden into the application's resource directory, then change any of the styles.

Styles:

Custom adapters

Example adapter:

public class CustomInAppMessageAdapter implements InAppMessageAdapter {

    private InAppMessage message;

    public CustomInAppMessageAdapter(InAppMessage message) {
        this.message = message;
    }


    @Override
    @PrepareResult
    public int onPrepare(@NonNull Context context) {
        // Download any resources for the in-app message before displaying

        return OK; // RETRY, CANCEL
    }

    @Override
    public boolean onDisplay(@NonNull Activity activity, boolean isRedisplay, DisplayHandler displayHandler) {
        // Display the in-app message
        Intent intent = new Intent(activity, CustomActivity.class)
                .putExtra(InAppMessageActivity.IN_APP_MESSAGE_KEY, message)
                .putExtra(InAppMessageActivity.DISPLAY_HANDLER_EXTRA_KEY, displayHandler);

        activity.startActivity(intent);

        return true; // false to retry later
    }

    @Override
    public void onFinish() {
        // Perform any clean up
    }
}

An example activity that displays a modal dialog:

public class CustomActivity extends InAppMessageActivity {

    @Override
    protected void onCreateMessage(@Nullable Bundle savedInstanceState) {
        InAppMessage message = getMessage();
        DisplayHandler displayHandler = getDisplayHandler();

        /* Request the display lock before showing an in-app message
        if (!displayHandler.requestDisplayLock(this)) {
            finish();
            return;
        }

        setContentView(R.layout.custom_view);

        ModalDisplayContent displayContent = message.getDisplayContent();

        // Bind display content to view
    }

    @Override
    protected void onStart() {
        super.onStart();

        // Request the display lock before showing an in-app message
        if (!displayHandler.requestDisplayLock(this)) {
            finish();
        }
    }

    public void onButtonPressed(ButtonInfo buttonInfo) {
        // Call the display handler once finished. This allows the next in-app message to be displayed.
        getDisplayHandler().finished(ResolutionInfo.buttonPressed(buttonInfo, getDisplayTime()));
        finish();
    }
}

Override the default modal factory to provide the new adapter:

UAirship.shared()
        .getInAppMessagingManager()
        .setAdapterFactory(InAppMessage.TYPE_MODAL, new InAppMessageAdapter.Factory() {
            @Override
            public InAppMessageAdapter createAdapter(InAppMessage message) {
                return new CustomInAppMessageAdapter(message);
            }
        });

Providing an adapter allows full customization for any message type. The adapter will be created by the in-app messaging manager when a message's schedule is triggered. Once created, the adapter will be called to first prepare the in-app message, giving the adapter time to download any resources such as images. After the adapter prepares the message, the adapter will be called to display the message.

After the message is displayed, the provided display handler must be notified that the message is finished displaying by calling the finished method. This will allow other in-app messages to be displayed.

Standard In-App Messages

Setting an schedule info builder extender:

UAirship.shared()
        .getLegacyInAppMessageManager()
        .setScheduleBuilderExtender(new LegacyInAppMessageManager.ScheduleInfoBuilderExtender() {
            @NonNull
            @Override
            public InAppMessageScheduleInfo.Builder extend(Context context, InAppMessageScheduleInfo.Builder builder, LegacyInAppMessage legacyMessage) {
                // Provide any changes to the builder
                return builder;
            }
        });

Setting an message builder extender:

UAirship.shared()
        .getLegacyInAppMessageManager()
        .setMessageBuilderExtender(new LegacyInAppMessageManager.MessageBuilderExtender() {
            @NonNull
            @Override
            public InAppMessage.Builder extend(Context context, InAppMessage.Builder builder, LegacyInAppMessage legacyMessage) {
                // Provide any changes to the builder

                return builder;
            }

        });

Standard in-app messages delivered through push messages are managed by the legacy in-app message manager. The manager converts the standard in-app message into a new in-app message schedule. The conversion can be customized by setting a builder extender to extend either the schedule builder or the message builder.

For more information on how to customize this conversion process, see the In-App Messages Migration guide.