MMKV is an efficient, small, easy-to-use mobile key-value storage framework used in the WeChat application.
—
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.
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");
}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();
}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();
}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);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");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);
}
}// 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); // Synchronizedpublic 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;
}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 modeInstall with Tessl CLI
npx tessl i tessl/maven-com-tencent--mmkv-shared