This guide covers the breaking changes introduced in mParticle Android SDK 6.0.0 and how to migrate your code to the new APIs.
The isAndroidIdDisabled() method on MParticle and MParticleOptions, and the androidIdDisabled(boolean) builder method on MParticleOptions.Builder, have been removed. These were replaced by inverted equivalents with clearer semantics.
Replace isAndroidIdDisabled() with isAndroidIdEnabled() and invert the logic:
Java:
// Before
if (MParticle.isAndroidIdDisabled()) { ... }
if (options.isAndroidIdDisabled()) { ... }
// After
if (!MParticle.isAndroidIdEnabled()) { ... }
if (!options.isAndroidIdEnabled()) { ... }Kotlin:
// Before
if (MParticle.isAndroidIdDisabled()) { ... }
if (options.isAndroidIdDisabled()) { ... }
// After
if (!MParticle.isAndroidIdEnabled()) { ... }
if (!options.isAndroidIdEnabled()) { ... }Replace androidIdDisabled(boolean) with androidIdEnabled(boolean) and invert the value:
Java:
// Before
MParticleOptions.builder(context)
.androidIdDisabled(true)
.build();
// After
MParticleOptions.builder(context)
.androidIdEnabled(false)
.build();Kotlin:
// Before
MParticleOptions.builder(context)
.androidIdDisabled(true)
.build()
// After
MParticleOptions.builder(context)
.androidIdEnabled(false)
.build()The isAutoTrackingEnabled() method on MParticle has been removed. This method always returned false and automatic screen tracking via activity lifecycle hooks has been removed.
Remove any calls to isAutoTrackingEnabled(). If your code depends on this value, note that it was always false — no screen tracking was being performed automatically.
Java:
// Before
if (MParticle.getInstance().isAutoTrackingEnabled()) {
// this block was never executed
}
// After
// Remove the call entirelyKotlin:
// Before
if (MParticle.getInstance()?.isAutoTrackingEnabled == true) {
// this block was never executed
}
// After
// Remove the call entirelyThe isProviderActive(int) method on MParticle has been removed. It has been renamed to isKitActive(int).
Replace isProviderActive(serviceProviderId) with isKitActive(serviceProviderId):
Java:
// Before
boolean active = MParticle.getInstance().isProviderActive(MParticle.ServiceProviders.APPBOY);
// After
boolean active = MParticle.getInstance().isKitActive(MParticle.ServiceProviders.APPBOY);Kotlin:
// Before
val active = MParticle.getInstance()?.isProviderActive(MParticle.ServiceProviders.APPBOY)
// After
val active = MParticle.getInstance()?.isKitActive(MParticle.ServiceProviders.APPBOY)The setInfo(Map), getInfo(), and Builder.info(Map) methods on MPEvent have been removed. They have been renamed to setCustomAttributes(), getCustomAttributes(), and Builder.customAttributes().
Replace usages with the new method names:
Java:
// Before
MPEvent event = new MPEvent.Builder("Event Name", MParticle.EventType.Other)
.info(attributes)
.build();
Map<String, String> info = event.getInfo();
event.setInfo(attributes);
// After
MPEvent event = new MPEvent.Builder("Event Name", MParticle.EventType.Other)
.customAttributes(attributes)
.build();
Map<String, ?> customAttributes = event.getCustomAttributes();
event.setCustomAttributes(attributes);Kotlin:
// Before
val event = MPEvent.Builder("Event Name", MParticle.EventType.Other)
.info(attributes)
.build()
val info = event.getInfo()
event.setInfo(attributes)
// After
val event = MPEvent.Builder("Event Name", MParticle.EventType.Other)
.customAttributes(attributes)
.build()
val customAttributes = event.getCustomAttributes()
event.setCustomAttributes(attributes)The com.mparticle.UserAttributeListener interface has been removed. It has been replaced by com.mparticle.TypedUserAttributeListener.
The key difference is that onUserAttributesReceived now receives Map<String, Any?> instead of Map<String, String?> for user attribute singles, allowing typed values (numbers, booleans) to be preserved rather than stringified. Additionally, the mpid parameter is non-nullable (Long instead of Long?).
Java:
// Before
user.getUserAttributes(new UserAttributeListener() {
@Override
public void onUserAttributesReceived(
@Nullable Map<String, String> userAttributes,
@Nullable Map<String, List<String>> userAttributeLists,
@Nullable Long mpid
) {
// handle attributes
}
});
// After
user.getUserAttributes(new TypedUserAttributeListener() {
@Override
public void onUserAttributesReceived(
@NonNull Map<String, ?> userAttributes,
@NonNull Map<String, ? extends List<String>> userAttributeLists,
long mpid
) {
// handle attributes — values may be String, Number, or null
}
});Kotlin:
// Before
user.getUserAttributes(UserAttributeListener { userAttributes, userAttributeLists, mpid ->
// userAttributes: Map<String, String?>?
})
// After
user.getUserAttributes(object : TypedUserAttributeListener {
override fun onUserAttributesReceived(
userAttributes: Map<String, Any?>,
userAttributeLists: Map<String, List<String?>?>,
mpid: Long
) {
// userAttributes values may be String, Number, Boolean, or null
}
})Note: numeric and boolean attribute values are no longer automatically converted to strings. If you need string values, call .toString() on each value manually.
The com.mparticle.identity.UserAliasHandler interface and the IdentityApiRequest.Builder.userAliasHandler() method have been removed. Use a success listener on the BaseIdentityTask returned by identity API calls instead.
Java:
// Before
IdentityApiRequest request = IdentityApiRequest.withEmptyUser()
.email("user@example.com")
.userAliasHandler(new UserAliasHandler() {
@Override
public void onUserAlias(MParticleUser previousUser, MParticleUser newUser) {
// copy attributes from previousUser to newUser
}
})
.build();
MParticle.getInstance().Identity().login(request);
// After
IdentityApiRequest request = IdentityApiRequest.withEmptyUser()
.email("user@example.com")
.build();
MParticle.getInstance().Identity().login(request)
.addSuccessListener(new TaskSuccessListener() {
@Override
public void onSuccess(IdentityApiResult result) {
MParticleUser newUser = result.getUser();
MParticleUser previousUser = result.getPreviousUser();
if (previousUser != null) {
// copy attributes from previousUser to newUser
}
}
});Kotlin:
// Before
val request = IdentityApiRequest.withEmptyUser()
.email("user@example.com")
.userAliasHandler { previousUser, newUser ->
// copy attributes from previousUser to newUser
}
.build()
MParticle.getInstance()?.Identity()?.login(request)
// After
val request = IdentityApiRequest.withEmptyUser()
.email("user@example.com")
.build()
MParticle.getInstance()?.Identity()?.login(request)
?.addSuccessListener { result ->
val newUser = result.user
val previousUser = result.previousUser
// copy attributes from previousUser to newUser
}The setCCPAConsent(CCPAConsent) and removeCCPAConsent() methods on ConsentState.Builder have been removed. They have been renamed to setCCPAConsentState(CCPAConsent) and removeCCPAConsentState().
Java:
// Before
ConsentState state = ConsentState.builder()
.setCCPAConsent(CCPAConsent.builder(true).build())
.build();
ConsentState.builder().removeCCPAConsent();
// After
ConsentState state = ConsentState.builder()
.setCCPAConsentState(CCPAConsent.builder(true).build())
.build();
ConsentState.builder().removeCCPAConsentState();Kotlin:
// Before
val state = ConsentState.builder()
.setCCPAConsent(CCPAConsent.builder(true).build())
.build()
ConsentState.builder().removeCCPAConsent()
// After
val state = ConsentState.builder()
.setCCPAConsentState(CCPAConsent.builder(true).build())
.build()
ConsentState.builder().removeCCPAConsentState()Rokt APIs are now owned by the Rokt kit module. Usage remains the same (MParticle.getInstance().Rokt()); update imports to use the kit package types.
Kotlin:
// Before
import com.mparticle.Rokt
val rokt = MParticle.getInstance()?.Rokt()
// After
import com.mparticle.kits.Rokt
val rokt = MParticle.getInstance()?.Rokt()Java:
// Before
com.mparticle.Rokt rokt = MParticle.getInstance().Rokt();
// After
com.mparticle.kits.Rokt rokt = MParticle.getInstance().Rokt();The following mParticle wrapper types were removed:
com.mparticle.RoktEventcom.mparticle.MpRoktEventCallbackcom.mparticle.rokt.RoktConfigcom.mparticle.rokt.PlacementOptions
Use native Rokt SDK types instead:
com.rokt.roktsdk.RoktEventcom.rokt.roktsdk.Rokt.RoktCallbackcom.rokt.roktsdk.RoktConfigcom.rokt.roktsdk.PlacementOptions
Kotlin:
// Before
val callback = object : MpRoktEventCallback { /* ... */ }
val config = com.mparticle.rokt.RoktConfig.Builder().build()
// After
val callback = object : com.rokt.roktsdk.Rokt.RoktCallback { /* ... */ }
val config = com.rokt.roktsdk.RoktConfig.Builder().build()prepareAttributesAsync is now internal to the kit implementation and should not be called directly from app code.