CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-tencent--mmkv-shared

MMKV is an efficient, small, easy-to-use mobile key-value storage framework used in the WeChat application.

Pending
Overview
Eval results
Files

multi-process.mddocs/

Multi-Process Support

Advanced multi-process functionality for safe concurrent access across Android processes. MMKV provides robust inter-process synchronization, locking mechanisms, and content change notifications for multi-process Android applications.

Capabilities

Inter-Process Locking

Exclusive locking mechanisms to ensure safe concurrent access across multiple processes.

/**
 * Exclusively inter-process lock the MMKV instance.
 * It will block and wait until it successfully locks the file.
 * It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
 */
public void lock();

/**
 * Exclusively inter-process unlock the MMKV instance.
 * It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
 */
public void unlock();

/**
 * Try exclusively inter-process lock the MMKV instance.
 * It will not block if the file has already been locked by another process.
 * It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
 * @return True if successfully locked, otherwise return immediately with False
 */
public boolean tryLock();

Usage Example:

// Create multi-process MMKV instance
MMKV multiProcessKv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE);

// Critical section with blocking lock
multiProcessKv.lock();
try {
    // Perform atomic operations
    int counter = multiProcessKv.decodeInt("global_counter", 0);
    counter++;
    multiProcessKv.encode("global_counter", counter);
    multiProcessKv.encode("last_updated", System.currentTimeMillis());
} finally {
    multiProcessKv.unlock();
}

// Non-blocking lock attempt
if (multiProcessKv.tryLock()) {
    try {
        // Quick operation that shouldn't wait
        multiProcessKv.encode("process_status", "active");
    } finally {
        multiProcessKv.unlock();
    }
} else {
    Log.d("MMKV", "Could not acquire lock, skipping update");
}

Content Change Detection

Monitor changes made by other processes to shared MMKV instances.

/**
 * Check inter-process content change manually.
 */
public void checkContentChangedByOuterProcess();

/**
 * Register for MMKV inter-process content change notification.
 * The notification will trigger only when any method is manually called on the MMKV instance.
 * @param notify The notification handler
 */
public static void registerContentChangeNotify(MMKVContentChangeNotification notify);

/**
 * Unregister for MMKV inter-process content change notification.
 */
public static void unregisterContentChangeNotify();

Usage Example:

// Register global content change notification
MMKV.registerContentChangeNotify(new MMKVContentChangeNotification() {
    @Override
    public void onContentChangedByOuterProcess(String mmapID) {
        Log.d("MMKV", "Content changed by another process: " + mmapID);
        // Refresh UI or reload data
        refreshDataFromMMKV(mmapID);
    }
});

// Check for changes manually
MMKV sharedKv = MMKV.mmkvWithID("shared_config", MMKV.MULTI_PROCESS_MODE);
sharedKv.checkContentChangedByOuterProcess(); // Triggers notification if changed

// Unregister when no longer needed
@Override
protected void onDestroy() {
    super.onDestroy();
    MMKV.unregisterContentChangeNotify();
}

Process Mode Validation

Validate and manage process mode settings for debugging multi-process access patterns.

/**
 * Manually enable the process mode checker.
 * By default, it's automatically enabled in DEBUG build, and disabled in RELEASE build.
 * If it's enabled, MMKV will throw exceptions when an MMKV instance is created with mismatch process mode.
 */
public static void enableProcessModeChecker();

/**
 * Manually disable the process mode checker.
 * By default, it's automatically enabled in DEBUG build, and disabled in RELEASE build.
 * If it's enabled, MMKV will throw exceptions when an MMKV instance is created with mismatch process mode.
 */
public static void disableProcessModeChecker();

/**
 * Check if this instance is in multi-process mode.
 * @return true if multi-process mode, false otherwise
 */
public boolean isMultiProcess();

Usage Example:

// Enable process mode checking for debugging
if (BuildConfig.DEBUG) {
    MMKV.enableProcessModeChecker();
}

// Create instances with proper mode
MMKV singleProcessKv = MMKV.mmkvWithID("local_data", MMKV.SINGLE_PROCESS_MODE);
MMKV multiProcessKv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE);

// Verify process mode
if (multiProcessKv.isMultiProcess()) {
    Log.d("MMKV", "Instance supports multi-process access");
} else {
    Log.w("MMKV", "Instance is single-process only");
}

// Disable checking in production
if (!BuildConfig.DEBUG) {
    MMKV.disableProcessModeChecker();
}

Anonymous Shared Memory for Inter-Process Communication

Use Anonymous Shared Memory (ashmem) for temporary inter-process data sharing without persistent storage.

/**
 * Create an MMKV instance base on Anonymous Shared Memory, aka not synced to any disk files.
 * Anonymous Shared Memory on Android can't grow dynamically, must set an appropriate size on creation.
 * @param context The context of Android App, usually from Application
 * @param mmapID The unique ID of the MMKV instance
 * @param size The maximum size of the underlying Anonymous Shared Memory
 * @param mode The process mode of the MMKV instance, defaults to SINGLE_PROCESS_MODE
 * @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes)
 * @return MMKV instance
 * @throws RuntimeException if there's a runtime error
 */
public static MMKV mmkvWithAshmemID(Context context, String mmapID, int size, int mode, String cryptKey);

/**
 * Get an ashmem MMKV instance that has been initiated by another process.
 * @param mmapID The unique ID of the MMKV instance
 * @param fd The file descriptor of the ashmem of the MMKV file
 * @param metaFD The file descriptor of the ashmem of the MMKV crc file  
 * @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes)
 * @return MMKV instance
 * @throws RuntimeException if there's a runtime error
 */
public static MMKV mmkvWithAshmemFD(String mmapID, int fd, int metaFD, String cryptKey);

/**
 * Get the file descriptor of the ashmem of the MMKV file.
 * @return The file descriptor of the ashmem of the MMKV file
 */
public int ashmemFD();

/**
 * Get the file descriptor of the ashmem of the MMKV crc file.
 * @return The file descriptor of the ashmem of the MMKV crc file
 */
public int ashmemMetaFD();

Usage Example:

// Create ashmem instance for inter-process communication
MMKV ashmemKv = MMKV.mmkvWithAshmemID(
    this,
    "ipc_channel",
    1024 * 1024, // 1MB maximum size
    MMKV.MULTI_PROCESS_MODE,
    null
);

// Use for temporary data sharing
ashmemKv.encode("current_state", "processing");
ashmemKv.encode("progress", 45);
ashmemKv.encode("result_data", resultBytes);

// Get file descriptors for passing to other processes
int dataFD = ashmemKv.ashmemFD();
int metaFD = ashmemKv.ashmemMetaFD();

// In another process, recreate from file descriptors
MMKV receivedKv = MMKV.mmkvWithAshmemFD("ipc_channel", dataFD, metaFD, null);
String state = receivedKv.decodeString("current_state", "unknown");
int progress = receivedKv.decodeInt("progress", 0);

Multi-Process Data Import

Import data between MMKV instances across process boundaries.

/**
 * Import all key-value items from src MMKV instance.
 * @param src Source MMKV instance to import from
 * @return Count of items imported
 */
public long importFrom(MMKV src);

/**
 * Atomically migrate all key-values from an existent SharedPreferences to the MMKV instance.
 * @param preferences The SharedPreferences to import from
 * @return The total count of key-values imported
 */
public int importFromSharedPreferences(SharedPreferences preferences);

Usage Example:

// Import from another MMKV instance
MMKV sourceKv = MMKV.mmkvWithID("source_data", MMKV.SINGLE_PROCESS_MODE);
MMKV targetKv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE);

long importedCount = targetKv.importFrom(sourceKv);
Log.d("MMKV", "Imported " + importedCount + " items to multi-process instance");

// Migrate from SharedPreferences to multi-process MMKV
SharedPreferences oldPrefs = getSharedPreferences("old_prefs", MODE_PRIVATE);
MMKV newKv = MMKV.mmkvWithID("migrated_data", MMKV.MULTI_PROCESS_MODE);

int migratedCount = newKv.importFromSharedPreferences(oldPrefs);
Log.d("MMKV", "Migrated " + migratedCount + " preferences to MMKV");

Parcelable MMKV for Process Communication

Use ParcelableMMKV to pass MMKV instances across process boundaries via Binder.

/**
 * A helper class for MMKV based on Anonymous Shared Memory.
 */
public final class ParcelableMMKV implements Parcelable {
    /**
     * Create ParcelableMMKV from MMKV instance.
     * @param mmkv The MMKV instance to wrap
     */
    public ParcelableMMKV(MMKV mmkv);
    
    /**
     * Convert back to MMKV instance.
     * @return The MMKV instance, or null if invalid
     */
    public MMKV toMMKV();
    
    // Parcelable implementation
    public int describeContents();
    public void writeToParcel(Parcel dest, int flags);
    public static final Creator<ParcelableMMKV> CREATOR;
}

Usage Example:

// Create ashmem MMKV for cross-process sharing
MMKV ashmemKv = MMKV.mmkvWithAshmemID(
    this, "cross_process_data", 512 * 1024, MMKV.MULTI_PROCESS_MODE, null
);
ashmemKv.encode("shared_message", "Hello from main process");

// Wrap in Parcelable for IPC
ParcelableMMKV parcelableKv = new ParcelableMMKV(ashmemKv);

// Send via Intent to another process/activity
Intent intent = new Intent(this, OtherProcessActivity.class);
intent.putExtra("mmkv_instance", parcelableKv);
startActivity(intent);

// In receiving process/activity
ParcelableMMKV receivedParcelable = getIntent().getParcelableExtra("mmkv_instance");
if (receivedParcelable != null) {
    MMKV receivedKv = receivedParcelable.toMMKV();
    if (receivedKv != null) {
        String message = receivedKv.decodeString("shared_message", "");
        Log.d("MMKV", "Received: " + message);
    }
}

Multi-Process Best Practices

// 1. Always use MULTI_PROCESS_MODE for shared data
MMKV sharedKv = MMKV.mmkvWithID("shared_config", MMKV.MULTI_PROCESS_MODE);

// 2. Use locking for critical sections
sharedKv.lock();
try {
    // Atomic read-modify-write operations
    int counter = sharedKv.decodeInt("counter", 0);
    sharedKv.encode("counter", counter + 1);
} finally {
    sharedKv.unlock();
}

// 3. Monitor content changes from other processes
MMKV.registerContentChangeNotify(mmapID -> {
    // Refresh data when other processes make changes
    refreshLocalCache();
});

// 4. Use try-lock for non-critical operations
if (sharedKv.tryLock()) {
    try {
        sharedKv.encode("last_ping", System.currentTimeMillis());
    } finally {
        sharedKv.unlock();
    }
}

// 5. Separate single-process and multi-process data
MMKV localKv = MMKV.mmkvWithID("local_cache", MMKV.SINGLE_PROCESS_MODE); // Faster
MMKV sharedKv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE); // Synchronized

Types

public interface MMKVContentChangeNotification {
    /**
     * Inter-process content change notification.
     * Triggered by any method call, such as getXXX() or setXXX() or checkContentChangedByOuterProcess().
     * @param mmapID The unique ID of the changed MMKV instance
     */
    void onContentChangedByOuterProcess(String mmapID);
}

public final class ParcelableMMKV implements Parcelable {
    public ParcelableMMKV(MMKV mmkv);
    public MMKV toMMKV();
    public int describeContents();
    public void writeToParcel(Parcel dest, int flags);
    public static final Creator<ParcelableMMKV> CREATOR;
}

Constants

public static final int SINGLE_PROCESS_MODE = 1 << 0;  // Single-process mode (default)
public static final int MULTI_PROCESS_MODE = 1 << 1;   // Multi-process mode
public static final int READ_ONLY_MODE = 1 << 5;       // Read-only mode

Install with Tessl CLI

npx tessl i tessl/maven-com-tencent--mmkv-shared

docs

advanced-features.md

data-management.md

encryption.md

index.md

initialization.md

instance-management.md

multi-process.md

storage-operations.md

tile.json