This file enables AI agents to work autonomously on the Mixpanel Android SDK codebase. It synthesizes patterns from local AI systems into comprehensive cloud execution instructions.
Mixpanel Android SDK - A production analytics library used by thousands of Android applications worldwide. The SDK prioritizes reliability, thread safety, and backward compatibility above all else.
Critical Context Files:
CLAUDE.md- Core patterns and conventions.claude/context/discovered-patterns.md- Detailed coding standards.claude/context/architecture/system-design.md- System architecture.cursor/rules/- Behavioral enforcement rules.github/copilot-instructions.md- Persistent coding guidance
Before beginning any task:
# Verify environment
./gradlew --version # Should show Gradle with JDK 17
adb devices # Should show connected device/emulator for tests
# Clean build to ensure fresh state
./gradlew clean
# Run quick verification
./gradlew build- NEVER CRASH THE HOST APP - Wrap all operations in try-catch, fail silently with logging
- THREAD SAFETY - All public APIs must handle concurrent access correctly
- NO EXTERNAL DEPENDENCIES - Use only Android SDK and Java standard library
- BACKWARDS COMPATIBILITY - Never break existing public APIs
- DEFENSIVE PROGRAMMING - Check nulls, validate inputs, handle edge cases
Test Coverage Tasks:
- "Add comprehensive tests for feature flags functionality"
- "Create thread safety tests for all public APIs"
- "Add instrumented tests for offline mode behavior"
Systematic Refactoring:
- "Update all database operations to use new transaction pattern"
- "Add defensive null checks to all public methods"
- "Implement proper resource cleanup in all try-finally blocks"
Documentation:
- "Generate JavaDoc for all public API methods"
- "Create examples for each People API operation"
- "Document all configuration options with examples"
Code Quality:
- "Add MPLog statements to trace event flow"
- "Implement lazy initialization for expensive objects"
- "Ensure all constants follow CAPS_WITH_UNDERSCORES"
- UI/UX decisions (this is a library)
- Performance optimization without metrics
- Architecture changes
- API design decisions
- Breaking changes
package com.mixpanel.android.mpmetrics;
// Package-private by default
class InternalHelper {
private static final String LOGTAG = "MixpanelAPI.Helper";
// Immutable fields
private final Context mContext;
private final Object mLock = new Object();
InternalHelper(Context context) {
mContext = context.getApplicationContext(); // Prevent leaks
}
}// ALWAYS wrap operations
try {
riskyOperation();
} catch (Exception e) {
MPLog.e(LOGTAG, "Operation failed", e);
// Continue gracefully - NEVER re-throw
}// Queue to background thread
Message msg = Message.obtain();
msg.what = ENQUEUE_EVENTS;
msg.obj = new EventDescription(event, properties, token);
mMessages.enqueueMessage(msg);@RunWith(AndroidJUnit4.class)
@LargeTest
public class FeatureTest {
private BlockingQueue<String> mMessages;
@Test
public void testAsync() throws Exception {
mMixpanel.track("Event");
String message = mMessages.poll(2, TimeUnit.SECONDS);
assertNotNull("Should receive message", message);
}
}Before submitting any PR, you MUST:
./gradlew clean :analytics:build
# Must pass with no errors or warnings# Run all instrumented tests (requires device/emulator)
# IMPORTANT: Run from the analytics module, not :analytics:mixpaneldemo
./gradlew :analytics:connectedAndroidTest
# All tests must pass
# Run specific test class
./gradlew :analytics:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.mixpanel.android.mpmetrics.TestClassName
# Run specific test method
./gradlew :analytics:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.mixpanel.android.mpmetrics.TestClassName#testMethodName./gradlew :analytics:lint
# Review any warnings in analytics/build/reports/lint-results-debug.html
./gradlew :analytics:animalsnifferRelease
# Fails on Java 9+ APIs and unguarded Android calls above minSdk.
# Report at analytics/build/reports/animalsniffer/release.text# Test with demo app
./gradlew :analytics:mixpaneldemo:installDebug
# Manually verify the feature works- No new external dependencies added
- All new code has try-catch blocks
- Thread safety verified for concurrent access
- Instrumented tests added for new features
- No breaking changes to public APIs
- JavaDoc added for public methods
- Follows 'm' prefix convention for fields
- Uses application context (not Activity)
Data Flow: MixpanelAPI → AnalyticsMessages → MPDbAdapter → HttpService
NEVER:
- Skip layers (e.g., MixpanelAPI calling HttpService directly)
- Create new public classes (keep internals package-private)
- Add Service or ContentProvider components
- Use reflection or dynamic class loading
- Create unit tests (instrumented only)
- Activity Context - Always use application context
- Synchronization - Use dedicated lock objects, not 'this'
- Resource Cleanup - Always close Cursors in finally blocks
- Testing - Must use BlockingQueue for async verification
- Configuration - Respect hierarchy: Runtime > Manifest > Default
Your PR description should include:
## Summary
- Added comprehensive tests for [feature]
- Improved thread safety in [component]
- Fixed resource leak in [class]
## Changes
- Added X new test cases
- Updated Y classes to follow patterns
- Cleaned up Z resources properly
## Testing
- [x] All tests pass locally
- [x] Demo app tested manually
- [x] No memory leaks detected
- [x] Thread safety verified
## Validation
- `./gradlew :analytics:build` - ✅ Passed
- `./gradlew :analytics:connectedAndroidTest` - ✅ All tests pass
- `./gradlew :analytics:lint` - ✅ No new warnings
- `./gradlew :analytics:animalsnifferRelease` - ✅ No API compatibility violationsYour task is successful when:
- All existing tests still pass
- New tests provide meaningful coverage
- Code follows established patterns exactly
- No external dependencies introduced
- PR can be merged without modification
- Visibility: Package-private by default
- Fields: Private final with 'm' prefix
- Errors: Catch all, log, continue
- Threading: HandlerThread + Messages
- Testing: Instrumented only with BlockingQueue
- Context: Application context always
- Database: Try-finally for Cursors
- API: Overload for convenience, null for optional
Remember: This SDK is critical infrastructure. Reliability > Features. When in doubt, check the patterns in .claude/context/discovered-patterns.md.