1. Home
  2. Developer Guides
  3. [Beta] Android SDK 6.0 – Native
  4. Android SDK 5.x.x to 6.0.0-betaxx Migration Guide

Android SDK 5.x.x to 6.0.0-betaxx Migration Guide

This guide is intended for app developers who have been using the Java-based Apptentive Android SDK and are migrating to the new Kotlin-based Android SDK.

Major Differences

The new Android SDK is a ground-up rewrite of the legacy Apptentive Android SDK in Kotlin using modern programming practices.

A few quick notes for getting started on the migration:

  • We now have a Kotlin codebase instead of Java
  • The screen’s Activity is now registered separately to the SDK. 
    • This allows the engage function to be called without needing to provide an Activity context.
  • Callback types are different when you engage events and when you register the SDK
  • Modular-based SDK

New Features

  • Interaction Response Targeting

Improvements

Current limitations

Most styles in 5.8.3 and prior have been deprecated and replaced with new styles in 6.0.0.

Some styles have been moved over, such as many text size, text color, and typeface styles, but the vast majority of styles have been changed.

The new styles have much better flexibility, many more options, better organization, and better naming patterns.

If you are starting fresh, the possibilities are huge. Check out the UI Cookbook for examples.

Refer to the Beta Interface Customization article for more help.

We do not recommend you migrate yet if you need any of the three features listed below.

These features will be implemented in the future.

  • The minimum supported Android version is now Android 5.0 (API level 21)
  • Message Center is not yet implemented
    • This will be added by the time 6.0.0 (not beta) is released
  • Encryption is not yet supported
    • Data migration will currently fail if you have used Encryption
  • Client Authentication (Multi-User / Login / Logout) is not yet supported

Java Apps

Due to Kotlin to Java interoperability limitations, our internal APIs are exposed when integrating from Java apps. We do not recommend you directly use our internal and @InternalUseOnly annotated fields as they are subject to change without notice.

Dependency Implementation

In your build.gradle file, add the following dependency to integrate Apptentive SDK, replacing APPTENTIVE_VERSIONwith the most recent one:

dependencies {
    implementation "com.apptentive:apptentive-kit-android:APPTENTIVE_VERSION"
}

Registering the SDK

Shortly after the app launch, you’ll want your app to call the register method. This should usually happen within your Application class. You’ll create an ApptentiveConfiguration object to pass in the Apptentive App Key and Apptentive App Signature values from the API & Development section of the Settings tab in your Apptentive dashboard. For more information on the optional ApptentiveConfiguration parameters, see the Apptentive Configuration optional parameters section.

Kotlin example:

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        val configuration = ApptentiveConfiguration(
        apptentiveKey = "<YOUR_APPTENTIVE_KEY>",
        apptentiveSignature = "<YOUR_APPTENTIVE_SIGNATURE>"
        ).apply {
            /**
            * Optional parameters:
            * shouldInheritAppTheme - Default is true
            * logLevel - Default is LogLevel.Info
            * shouldSanitizeLogMessages - Default is true
            * ratingInteractionThrottleLength - Default is TimeUnit.DAYS.toMillis(7)
            * customAppStoreURL - Default is null (Rating Interaction attempts to show Google In-App Review)
            */
        }
        Apptentive.register(this, configuration)
    }
}

Java example:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        /*
        * Optional parameters:
        * shouldInheritAppTheme - Default is true
        * logLevel - Default is LogLevel.Info
        * shouldSanitizeLogMessages - Default is true
        * ratingInteractionThrottleLength - Default is TimeUnit.DAYS.toMillis(7)
        * customAppStoreURL - Default is null (Rating Interaction attempts to show Google In-App Review)
        */
        ApptentiveConfiguration configuration = new ApptentiveConfiguration(
            "<YOUR_APPTENTIVE_KEY>",
            "<YOUR_APPTENTIVE_SIGNATURE>"
        );
  
        Apptentive.register(this, configuration);
    }
}

If you didn’t already have an Application class defined in your app, you will need to create one and add it to your Manifest.

Using Registration Callbacks

Our registration callbacks help you debug the Apptentive SDK.

Kotlin example:

Apptentive.register(this, configuration) {
    when (it) {
        is RegisterResult.Success -> Log.i(
            "Apptentive Registration",
            "Registration successful"
        )
        is RegisterResult.Failure -> Log.w(
            "Apptentive Registration",
            "Registration failed with response code: ${it.responseCode} and error message: ${it.message}"
        )
        is RegisterResult.Exception -> Log.e(
            "Apptentive Registration",
            "Registration failed with exception",
            it.error
        )
    }
}

Java example:

Apptentive.register(this, configuration, result -> {
    if (result instanceof RegisterResult.Success) {
        Log.i("Apptentive Registration", "Registration successful");
    } else if (result instanceof RegisterResult.Failure) {
        RegisterResult.Failure resultFailure = (RegisterResult.Failure) result;
        Log.w(
            "Apptentive Registration",
            "Registration failed with response code: " + resultFailure.getResponseCode() +
            ", and error message: " + resultFailure.getMessage()
        );
    } else if (result instanceof RegisterResult.Exception) {
        RegisterResult.Exception resultError = (RegisterResult.Exception) result;
        Log.e("Apptentive Registration", "Registration failed with an exception", resultError.getError());
    }
});

Registering/Unregistering the Activity Callback to the SDK

With the re-write of the SDK, we leveraged a modern architecture using modules. This allows for greater flexibility in where the engage method can be called from.

The Apptentive SDK now needs to register the Activity to the SDK in order to show our Interactions in your application.

This will need to be done for every Activity within your application.

We recommend that you implement this within a BaseActivity that your other Activities can extend from or use Android Jetpack Navigation. This will enable you to implement this a minimum number of times.

This is a 3 step process:

  1. Extend the ApptentiveActivityInfo interface to your Activity
  2. Override the getApptentiveActivityInfo function
    1. You will just return this (the Activity)
  3. Register the callback with the Apptentive SDK using the registerApptentiveActivityInfoCallback function within your onResume function (after the super)
  4. Unregister the callback using unregisterApptentiveActivityInfoCallback function within your onPause function(before the super)

Kotlin example:

class MainActivity : AppCompatActivity(), ApptentiveActivityInfo {
    override fun onResume() {
        super.onResume()
        Apptentive.registerApptentiveActivityInfoCallback(this)
    }

    override fun getApptentiveActivityInfo(): Activity {
        return this
    }

    override fun onPause() {
        Apptentive.unregisterApptentiveActivityInfoCallback(this)
        super.onPause()
    }
}

Java example:

public class MainActivity extends AppCompatActivity implements ApptentiveActivityInfo {
    @Override
    protected void onResume() {
        super.onResume();
        Apptentive.registerApptentiveActivityInfoCallback(this);
    }

    @NonNull
    @Override
    public Activity getApptentiveActivityInfo() {
        return this;
    }
  
    @Override
    protected void onPause() {
        Apptentive.unregisterApptentiveActivityInfoCallback(this);
        super.onPause();
    }
}

Engaging Events

At various points in your app’s lifecycle, you will want to engage events with the Apptentive SDK in order to allow the targeting and the launch of Apptentive’s interactions (Surveys, Notes, Love Dialog, etc.).

Kotlin example:

// Engaging
Apptentive.engage("my_event")

// Engaging with callback (optional)
Apptentive.engage("my_event") { result ->
    when (result) {
        is EngagementResult.InteractionShown -> { /* Interaction was shown */ }
        is EngagementResult.InteractionNotShown -> { /* Interaction was NOT shown */ }
        is EngagementResult.Error -> { /* There was an error during evaluation */ } 
        is EngagementResult.Exception -> { /* Something went wrong */ } 
    }
}

Java example:

// Engaging
Apptentive.engage("my_event");

// Engaging with callback (optional)
Apptentive.engage("my_event", result -> {
    if (result instanceof EngagementResult.InteractionShown) {
        /* Interaction was shown */
    } else if (result instanceof EngagementResult.InteractionNotShown) {
        /* Interaction was NOT shown */
    } else if (result instanceof EngagementResult.Error) {
        /* There was an error during evaluation */
    } else if (result instanceof EngagementResult.Exception) {
        /* Something went wrong */
    }
});

Apptentive Configuration optional parameters

The configuration options are enabled with defaults that are production-ready.

  1. shouldInheritAppTheme
    1. A boolean that determines if Apptentive Interactions will use the host app’s theme or Apptentive’s theme.
    2. If true, Apptentive Interactions will use the host app’s theme and colors.
    3. If false, Apptentive Interactions will use the Theme.Apptentive theme and colors, set in the styles.xml file within the apptentive-core-ui package.
    4. ApptentiveThemeOverride will always take priority over all themes.
    5. See ThemeHelper.kt within the apptentive-core-ui package for more info.
  2. logLevel
    1. An enum used to define what level of logs we will show in Android Studio’s Logcat
    2. Default is LogLevel.Info
    3. Log level options are
      1. LogLevel.Verbose
        1. Any relevant info not shown in other log levels
      2. LogLevel.Debug
        1. Processes with more technical information
      3. LogLevel.Info
        1. General processes and non-technical results
      4. LogLevel.Warning
        1. Non-breaking / handled issues
      5. LogLevel.Error
        1. Breaking / unhandled issues (Throwables)
  3. shouldSanitizeLogMessages
    1. A boolean that declares whether or not to convert the data of variables using the @SensitiveDataKey annotation to <REDACTED>
    2. When true (default)
      1. Redacts sensitive information from Logcat
      2. Redacted information includes:
        1. Apptentive Key & Signature
        2. Conversation Token
        3. Server call
          1. Headers
          2. Request Body
          3. Response Body
        4. mParticle IDs
        5. Custom Data
        6. Legacy data while being converted
        7. SDK Author name and email
    3. When set to false
      1. All info above is available to be logged to Android Studio’s Logcat
        1. Whether or not it is logged depends on the set logLevel
  4. ratingInteractionThrottleLength
    1. A millisecond based rating interaction throttle
    2. Default is 7 days
      1. We are using TimeUnit of the java.util.concurrent library to help with Day to Millisecond conversions.
        1. TimeUnit.DAYS.toMillis(7)
    3. Hard limits the frequency that the user will see the Rating Interaction in a specified period of time
    4. This is an internal throttle safeguard outside of the defined limitations set in the dashboard
  5. customAppStoreURL
    1. A String based variable that is used for alternate app store ratings.
    2. If null (default), the user will see the Google In-App Review and will be able to leave an app rating directly to the Play Store without leaving the app.
    3. If set to a String, the SDK will ignore the Google In-App Review Interaction for the Apptentive Rating Dialog Interaction and will attempt to send the user to the specified URL if the user chooses to rate the app.

Styling

Migrating styling will be familiar, yet different. We have opened up more options for styling and kept most of the styling parameters while removing others in order to better support a wider range of styles.

Here’s an article on our interface customization currently available and how the default interaction UIs look.

Prerequisites

What’s new?

  • We are now using Material Design’s Material Components within our SDK (designed to be used with Material Design 2, but Material 3 will also work)
  • shouldInheritAppTheme will let you decide if you want to use Apptentive’s colors or if we should inherit your app’s colors
    • Default is true, which will inherit your app’s colors
  • Every layout, text, button, widget, and most other views on the screen now have their own customization attribute associated with it
  • We have removed all hard-coded stylings from the views themselves in order to give greater freedom when overriding our styles
  • We now have an alpha attribute that allows us to give text better visual priorities without needing separate similar text colors
    • These attributes are apptentiveHeaderAlpha and apptentiveSubheaderAlpha

Coming Soon

  • Android UI Cookbook with custom UI examples with code snippet

Deprecated Styles

Since our UI was updated, not all styles were able to migrate over or they did not translate well into the new architecture with new customization options.

Most styles in 5.8.3 and prior have been deprecated and replaced with new styles in 6.0.0.

Some styles have been moved over, such as many text size, text color, and typeface styles, but the vast majority of styles have been changed.

The new styles have much better flexibility, many more options, better organization, and better naming patterns.

Styles used within the ApptentiveThemeOverride style will only affect Apptentive Interactions. You won’t need to worry about style items like colorPrimary affecting your app’s styles if it is placed within the ApptentiveThemeOverride style.

Good alternatives to the deprecated styles are to override the view’s style individually and set any style items you want to it.

Apptentive Code Resources

How to override an Apptentive style

  1. Go to your styles.xml file (or create one)
  2. Add an ApptentiveThemeOverride style
<style name="ApptentiveThemeOverride"> 
	// Override items go here
</style>

Style Information

Style / Theme Hierarchy

  1. ApptentiveThemeOverride (set only by the developer in their styles.xml file) takes priority over all other stylings
  2. Second priority, we disable the style item android:background
    1. This is a problem style for many of our Material Design widgets
    2. We use android:colorBackground and colorSurface for background colors
    3. If you do need to use this, you can re-enable with ApptentiveThemeOverride
  3. Third priority, we apply the host app’s theme if shouldInheritAppTheme is set to true 
  4. Last priority, we apply Apptentive’s theme
    1. If shouldInheritAppTheme is false and you don’t have anything set in ApptentiveThemeOverride, you will be able to see Apptentive’s default theme

See ThemeHelper.kt for more info.

Important styles we inherit

We are following Material Theme guidelines for color styling

These do not need to be set within ApptentiveThemeOverride, we will inherit them automatically

Dialog colors (Love Dialog, Notes, Rating Dialog)
  • Background uses colorSurface
  • Non-button text uses colorOnSurface
  • Button text uses colorSecondary
Survey colors
  • Toolbar (top and bottom) background uses colorPrimary
  • Toolbar (top and bottom) text uses colorOnPrimary
  • Activity main background uses android:colorBackground
  • Question Text uses colorOnBackground
  • Question Widgets use a combination of colorOnBackground and colorSecondary
  • Question Error Text uses colorError
  • Submit button uses colorPrimary
  • Submit button text uses colorOnPrimary

Logging

To set the severity of log messages shown in the logs, set the Apptentive LogLevel. The default is set to LogLevel.Info.

Kotlin example:

val configuration = ApptentiveConfiguration(...)
configuration.logLevel = LogLevel.DEBUG
Apptentive.register(this, configuration)

Java example:

ApptentiveConfiguration configuration = new ApptentiveConfiguration(...)
configuration.setLogLevel(LogLevel.Debug);
Apptentive.register(this, configuration);

Example App

apptentive-example

A simple app to help customers integrate with the Apptentive Android SDK

Instructions

  1. Download and open the example app in Android Studio
  2. Click the TODO tab at the bottom left of Android Studio to follow step-by-step instructions on where and how to create a very basic Apptentive integrated Android app.
Updated on June 23, 2022

Was this article helpful?

Related Articles