Custom Message Center Display

This guide shows the minimum integration necessary to display a Message Center message in a custom webview.

While the Airship SDK provides built-in Message Center UI, sometimes it can be useful to create a custom implementation that bypasses the default implementation’s view hierarchy. Message Center messages are just HTML, and so they can be displayed in any webview. However, there are a few integration steps needed to ensure that authorization and the Native Bridge function properly.

Authentication

Message Center messages are fetched with basic authentication using the User credentials in base64 encoding. This class persists a unique username and password to the device, and provides easy access to the information at runtime.

User user = MessageCenter().shared().getUser();
String username = user.getId();
String password = user.getPassword();

if (user.getId() != null && user.getPassword() != null) {
   // set auth here
}
val user = MessageCenter().shared().user
val username = user.id
val password = user.password

if (user.id != null && user.password != null) {
   // set auth here
}

We will look at a more detailed example in the context of a custom webView further below.

Setting up the Native Bridge

The Airship Native bridge works by intercepting all links with the uairship:// scheme and translating specially URL-encoded paths into native commands and arguments. To do this in a custom web view, use or extend the MessageWebViewClient, which handles the injection of JavaScript and related lifecycle callbacks.

Setting MessageWebViewClient and Loading A Message

The example below shows how to put these pieces together in the context of a custom WebView class. An anonymous inner class extends MessageWebViewClient to pass along auth credentials from the User

public class MyWebView extends WebView {

   private final MessageWebViewClient webViewClient = new MessageWebViewClient();


   public void initClient() {
      setWebViewClient(webViewClient);
   }

   // load a message with auth set in the headers
   public void loadMessage(Message message) {
      User user = MessageCenter.shared().getUser();

      // Send authorization in the headers if the web view supports it
      HashMap<String, String> headers = new HashMap<>();
      if (user.getId() != null && user.getPassword() != null) {
         webViewClient.addAuthRequestCredentials(message.getMessageBodyUrl(), user.getId(), user.getPassword());
         headers.put("Authorization", createBasicAuth(user.getId(), user.getPassword()));
      }

      loadUrl(message.getMessageBodyUrl(), headers);
   }

   // helper method for creating base64-encoded, basic auth header values
   private String createBasicAuth(@NonNull String userName, @NonNull String password) {
      String credentials = userName + ":" + password;
      return "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
   }
}
class MyWebView(context: Context) : WebView(context) {

    val messageWebViewClient = MessageWebViewClient()

    init {
        this.webViewClient = messageWebViewClient
    }

    // load a message with auth set in the headers
    fun loadMessage(message: Message) {
        val user = MessageCenter.shared().user

        // Send authorization in the headers if the web view supports it
        var headers: HashMap<String, String> = HashMap()
        if (user.id != null && user.password != null) {
            messageWebViewClient.addAuthRequestCredentials(message.messageBodyUrl, user.id, user.password)
            headers["Authorization"] = createBasicAuth(user.id!!, user.password!!);
        }

        loadUrl(message.messageBodyUrl, headers)
    }

    // helper method for creating base64-encoded, basic auth header values
    private fun createBasicAuth(userName: String, password: String): String {
        val credentials: String = "$userName:$password"
        return "Basic " + Base64.encodeToString(credentials.toByteArray(), Base64.NO_WRAP)
    }
}