Skip to content

Conversation

@jaredmixpanel
Copy link
Collaborator

@jaredmixpanel jaredmixpanel commented Jan 13, 2026

Summary

Ports the deviceIdProvider feature from the Swift SDK (PR #692) to Android, allowing customers to supply their own device ID generation logic.

  • DeviceIdProvider interface - Functional interface for custom device ID generation
  • MixpanelOptions.Builder.deviceIdProvider() - Configuration entry point
  • PersistentIdentity integration - Uses provider during identity initialization and reset
  • Identity continuity protection - Persisted IDs take precedence when adding provider to existing app
  • Graceful fallback - Handles null/empty returns and exceptions by falling back to UUID generation

Key Behaviors

  • Provider returning the same value each time = persistent device ID (survives reset)
  • Provider returning a new value each time = ephemeral device ID (changes on reset)
  • Adding provider to existing app preserves persisted identity with warning log

API

MixpanelOptions options = new MixpanelOptions.Builder()
    .deviceIdProvider(() -> {
        // Option 1: Persistent - return same value each time
        return MyKeystoreHelper.getOrCreatePersistentId();
        
        // Option 2: Ephemeral - return different value each time
        // return UUID.randomUUID().toString();
        
        // Option 3: Fallback - return null on failure (SDK uses default UUID)
        // String id = fetchFromServer();
        // return id; // null triggers fallback
    })
    .build();

MixpanelAPI mixpanel = MixpanelAPI.getInstance(context, "YOUR_TOKEN", false, options);

Test Plan

  • 15 new instrumented tests in MixpanelDeviceIdProviderTest.java
  • All existing tests pass (updated to new 5-parameter signature)
  • Covers: basic usage, reset behavior, opt-out, migration warnings, persistence, edge cases

Documentation

See context/device-id-provider.md for complete API reference and usage examples.

GitHub Copilot Summary

This pull request introduces support for custom device ID generation in the Mixpanel Android SDK, enabling developers to control how device IDs are created and persisted. The main change is the addition of the DeviceIdProvider interface, which allows for flexible device ID strategies, including persistence across resets or ephemeral IDs that change on reset. Related updates ensure that this new provider is correctly integrated into the SDK and its tests.

Custom Device ID Provider Feature:

  • Added a new DeviceIdProvider interface, allowing developers to specify custom logic for device ID generation, with documentation and usage examples. (src/main/java/com/mixpanel/android/mpmetrics/DeviceIdProvider.java)
  • Added a detailed documentation file explaining how to use and implement custom device ID providers, including migration and error handling considerations. (context/device-id-provider.md)

Test and Internal API Updates:

Constructor Enhancements:

  • Added new constructors to test utilities to support initialization with MixpanelOptions, allowing injection of a custom device ID provider. (src/androidTest/java/com/mixpanel/android/mpmetrics/TestUtils.java)

These changes provide developers with full control over device identity management in Mixpanel, improving flexibility and supporting advanced privacy requirements.

Allows customers to supply their own device ID generation logic via the
DeviceIdProvider interface:
- Control where device IDs are stored (e.g., server-side, Keychain)
- Control whether device IDs persist across reset()/optOutTracking()
- Provider returning same value = persistent ID; different value = ephemeral ID

Identity continuity protection: when adding a provider to an existing app,
persisted IDs take precedence with a warning log if values differ.

Handles null/empty returns and exceptions gracefully by falling back to
UUID generation.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a DeviceIdProvider interface to enable custom device ID generation in the Mixpanel Android SDK, porting functionality from the Swift SDK. This allows developers to control device ID generation instead of relying on the SDK's default UUID-based approach.

Changes:

  • Introduces DeviceIdProvider functional interface for custom device ID generation with comprehensive documentation
  • Adds deviceIdProvider() configuration method to MixpanelOptions.Builder
  • Integrates provider into PersistentIdentity with defensive error handling, fallback logic, and identity continuity protection
  • Updates all existing test classes to accommodate the new 5-parameter getPersistentIdentity() signature
  • Adds 15 comprehensive instrumented tests covering basic functionality, reset behavior, opt-out, migration, persistence, and edge cases

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
DeviceIdProvider.java New functional interface with detailed documentation on usage patterns and threading considerations
MixpanelOptions.java Adds deviceIdProvider field and builder method with comprehensive documentation
PersistentIdentity.java Implements device ID generation logic with provider support, error handling, and identity continuity checks
MixpanelAPI.java Updates getPersistentIdentity() method signatures to pass provider through initialization chain
TestUtils.java Updates CleanMixpanelAPI to support new constructor signature
PersistentIdentityTest.java Passes null for new deviceIdProvider parameter
OptOutTest.java Updates all getPersistentIdentity() overrides to include new parameter
MixpanelBasicTest.java Updates test implementation overrides for new signature
AutomaticEventsTest.java Updates getPersistentIdentity() override
MixpanelDeviceIdProviderTest.java New comprehensive test suite with 15 tests covering all scenarios

- Cache provider result in readIdentities() to avoid calling provider twice
- Remove eager loading for DeviceIdProvider (use lazy loading like default UUID)
- Add @FunctionalInterface annotation to DeviceIdProvider interface
- Add @nullable annotation to MixpanelOptions.getDeviceIdProvider()
- Add @after cleanup method to MixpanelDeviceIdProviderTest
- Update test to verify lazy loading behavior
@jaredmixpanel
Copy link
Collaborator Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

The test was asserting provider call count before accessing identity,
but due to lazy loading the provider is only called on first identity access.
Copy link

@rahul-mixpanel rahul-mixpanel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍 Clean solution. Love it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants