0
# Multi-Process Support
1
2
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.
3
4
## Capabilities
5
6
### Inter-Process Locking
7
8
Exclusive locking mechanisms to ensure safe concurrent access across multiple processes.
9
10
```java { .api }
11
/**
12
* Exclusively inter-process lock the MMKV instance.
13
* It will block and wait until it successfully locks the file.
14
* It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
15
*/
16
public void lock();
17
18
/**
19
* Exclusively inter-process unlock the MMKV instance.
20
* It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
21
*/
22
public void unlock();
23
24
/**
25
* Try exclusively inter-process lock the MMKV instance.
26
* It will not block if the file has already been locked by another process.
27
* It will make no effect if the MMKV instance is created with SINGLE_PROCESS_MODE.
28
* @return True if successfully locked, otherwise return immediately with False
29
*/
30
public boolean tryLock();
31
```
32
33
**Usage Example:**
34
35
```java
36
// Create multi-process MMKV instance
37
MMKV multiProcessKv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE);
38
39
// Critical section with blocking lock
40
multiProcessKv.lock();
41
try {
42
// Perform atomic operations
43
int counter = multiProcessKv.decodeInt("global_counter", 0);
44
counter++;
45
multiProcessKv.encode("global_counter", counter);
46
multiProcessKv.encode("last_updated", System.currentTimeMillis());
47
} finally {
48
multiProcessKv.unlock();
49
}
50
51
// Non-blocking lock attempt
52
if (multiProcessKv.tryLock()) {
53
try {
54
// Quick operation that shouldn't wait
55
multiProcessKv.encode("process_status", "active");
56
} finally {
57
multiProcessKv.unlock();
58
}
59
} else {
60
Log.d("MMKV", "Could not acquire lock, skipping update");
61
}
62
```
63
64
### Content Change Detection
65
66
Monitor changes made by other processes to shared MMKV instances.
67
68
```java { .api }
69
/**
70
* Check inter-process content change manually.
71
*/
72
public void checkContentChangedByOuterProcess();
73
74
/**
75
* Register for MMKV inter-process content change notification.
76
* The notification will trigger only when any method is manually called on the MMKV instance.
77
* @param notify The notification handler
78
*/
79
public static void registerContentChangeNotify(MMKVContentChangeNotification notify);
80
81
/**
82
* Unregister for MMKV inter-process content change notification.
83
*/
84
public static void unregisterContentChangeNotify();
85
```
86
87
**Usage Example:**
88
89
```java
90
// Register global content change notification
91
MMKV.registerContentChangeNotify(new MMKVContentChangeNotification() {
92
@Override
93
public void onContentChangedByOuterProcess(String mmapID) {
94
Log.d("MMKV", "Content changed by another process: " + mmapID);
95
// Refresh UI or reload data
96
refreshDataFromMMKV(mmapID);
97
}
98
});
99
100
// Check for changes manually
101
MMKV sharedKv = MMKV.mmkvWithID("shared_config", MMKV.MULTI_PROCESS_MODE);
102
sharedKv.checkContentChangedByOuterProcess(); // Triggers notification if changed
103
104
// Unregister when no longer needed
105
@Override
106
protected void onDestroy() {
107
super.onDestroy();
108
MMKV.unregisterContentChangeNotify();
109
}
110
```
111
112
### Process Mode Validation
113
114
Validate and manage process mode settings for debugging multi-process access patterns.
115
116
```java { .api }
117
/**
118
* Manually enable the process mode checker.
119
* By default, it's automatically enabled in DEBUG build, and disabled in RELEASE build.
120
* If it's enabled, MMKV will throw exceptions when an MMKV instance is created with mismatch process mode.
121
*/
122
public static void enableProcessModeChecker();
123
124
/**
125
* Manually disable the process mode checker.
126
* By default, it's automatically enabled in DEBUG build, and disabled in RELEASE build.
127
* If it's enabled, MMKV will throw exceptions when an MMKV instance is created with mismatch process mode.
128
*/
129
public static void disableProcessModeChecker();
130
131
/**
132
* Check if this instance is in multi-process mode.
133
* @return true if multi-process mode, false otherwise
134
*/
135
public boolean isMultiProcess();
136
```
137
138
**Usage Example:**
139
140
```java
141
// Enable process mode checking for debugging
142
if (BuildConfig.DEBUG) {
143
MMKV.enableProcessModeChecker();
144
}
145
146
// Create instances with proper mode
147
MMKV singleProcessKv = MMKV.mmkvWithID("local_data", MMKV.SINGLE_PROCESS_MODE);
148
MMKV multiProcessKv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE);
149
150
// Verify process mode
151
if (multiProcessKv.isMultiProcess()) {
152
Log.d("MMKV", "Instance supports multi-process access");
153
} else {
154
Log.w("MMKV", "Instance is single-process only");
155
}
156
157
// Disable checking in production
158
if (!BuildConfig.DEBUG) {
159
MMKV.disableProcessModeChecker();
160
}
161
```
162
163
### Anonymous Shared Memory for Inter-Process Communication
164
165
Use Anonymous Shared Memory (ashmem) for temporary inter-process data sharing without persistent storage.
166
167
```java { .api }
168
/**
169
* Create an MMKV instance base on Anonymous Shared Memory, aka not synced to any disk files.
170
* Anonymous Shared Memory on Android can't grow dynamically, must set an appropriate size on creation.
171
* @param context The context of Android App, usually from Application
172
* @param mmapID The unique ID of the MMKV instance
173
* @param size The maximum size of the underlying Anonymous Shared Memory
174
* @param mode The process mode of the MMKV instance, defaults to SINGLE_PROCESS_MODE
175
* @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes)
176
* @return MMKV instance
177
* @throws RuntimeException if there's a runtime error
178
*/
179
public static MMKV mmkvWithAshmemID(Context context, String mmapID, int size, int mode, String cryptKey);
180
181
/**
182
* Get an ashmem MMKV instance that has been initiated by another process.
183
* @param mmapID The unique ID of the MMKV instance
184
* @param fd The file descriptor of the ashmem of the MMKV file
185
* @param metaFD The file descriptor of the ashmem of the MMKV crc file
186
* @param cryptKey The encryption key of the MMKV instance (no more than 16 bytes)
187
* @return MMKV instance
188
* @throws RuntimeException if there's a runtime error
189
*/
190
public static MMKV mmkvWithAshmemFD(String mmapID, int fd, int metaFD, String cryptKey);
191
192
/**
193
* Get the file descriptor of the ashmem of the MMKV file.
194
* @return The file descriptor of the ashmem of the MMKV file
195
*/
196
public int ashmemFD();
197
198
/**
199
* Get the file descriptor of the ashmem of the MMKV crc file.
200
* @return The file descriptor of the ashmem of the MMKV crc file
201
*/
202
public int ashmemMetaFD();
203
```
204
205
**Usage Example:**
206
207
```java
208
// Create ashmem instance for inter-process communication
209
MMKV ashmemKv = MMKV.mmkvWithAshmemID(
210
this,
211
"ipc_channel",
212
1024 * 1024, // 1MB maximum size
213
MMKV.MULTI_PROCESS_MODE,
214
null
215
);
216
217
// Use for temporary data sharing
218
ashmemKv.encode("current_state", "processing");
219
ashmemKv.encode("progress", 45);
220
ashmemKv.encode("result_data", resultBytes);
221
222
// Get file descriptors for passing to other processes
223
int dataFD = ashmemKv.ashmemFD();
224
int metaFD = ashmemKv.ashmemMetaFD();
225
226
// In another process, recreate from file descriptors
227
MMKV receivedKv = MMKV.mmkvWithAshmemFD("ipc_channel", dataFD, metaFD, null);
228
String state = receivedKv.decodeString("current_state", "unknown");
229
int progress = receivedKv.decodeInt("progress", 0);
230
```
231
232
### Multi-Process Data Import
233
234
Import data between MMKV instances across process boundaries.
235
236
```java { .api }
237
/**
238
* Import all key-value items from src MMKV instance.
239
* @param src Source MMKV instance to import from
240
* @return Count of items imported
241
*/
242
public long importFrom(MMKV src);
243
244
/**
245
* Atomically migrate all key-values from an existent SharedPreferences to the MMKV instance.
246
* @param preferences The SharedPreferences to import from
247
* @return The total count of key-values imported
248
*/
249
public int importFromSharedPreferences(SharedPreferences preferences);
250
```
251
252
**Usage Example:**
253
254
```java
255
// Import from another MMKV instance
256
MMKV sourceKv = MMKV.mmkvWithID("source_data", MMKV.SINGLE_PROCESS_MODE);
257
MMKV targetKv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE);
258
259
long importedCount = targetKv.importFrom(sourceKv);
260
Log.d("MMKV", "Imported " + importedCount + " items to multi-process instance");
261
262
// Migrate from SharedPreferences to multi-process MMKV
263
SharedPreferences oldPrefs = getSharedPreferences("old_prefs", MODE_PRIVATE);
264
MMKV newKv = MMKV.mmkvWithID("migrated_data", MMKV.MULTI_PROCESS_MODE);
265
266
int migratedCount = newKv.importFromSharedPreferences(oldPrefs);
267
Log.d("MMKV", "Migrated " + migratedCount + " preferences to MMKV");
268
```
269
270
### Parcelable MMKV for Process Communication
271
272
Use ParcelableMMKV to pass MMKV instances across process boundaries via Binder.
273
274
```java { .api }
275
/**
276
* A helper class for MMKV based on Anonymous Shared Memory.
277
*/
278
public final class ParcelableMMKV implements Parcelable {
279
/**
280
* Create ParcelableMMKV from MMKV instance.
281
* @param mmkv The MMKV instance to wrap
282
*/
283
public ParcelableMMKV(MMKV mmkv);
284
285
/**
286
* Convert back to MMKV instance.
287
* @return The MMKV instance, or null if invalid
288
*/
289
public MMKV toMMKV();
290
291
// Parcelable implementation
292
public int describeContents();
293
public void writeToParcel(Parcel dest, int flags);
294
public static final Creator<ParcelableMMKV> CREATOR;
295
}
296
```
297
298
**Usage Example:**
299
300
```java
301
// Create ashmem MMKV for cross-process sharing
302
MMKV ashmemKv = MMKV.mmkvWithAshmemID(
303
this, "cross_process_data", 512 * 1024, MMKV.MULTI_PROCESS_MODE, null
304
);
305
ashmemKv.encode("shared_message", "Hello from main process");
306
307
// Wrap in Parcelable for IPC
308
ParcelableMMKV parcelableKv = new ParcelableMMKV(ashmemKv);
309
310
// Send via Intent to another process/activity
311
Intent intent = new Intent(this, OtherProcessActivity.class);
312
intent.putExtra("mmkv_instance", parcelableKv);
313
startActivity(intent);
314
315
// In receiving process/activity
316
ParcelableMMKV receivedParcelable = getIntent().getParcelableExtra("mmkv_instance");
317
if (receivedParcelable != null) {
318
MMKV receivedKv = receivedParcelable.toMMKV();
319
if (receivedKv != null) {
320
String message = receivedKv.decodeString("shared_message", "");
321
Log.d("MMKV", "Received: " + message);
322
}
323
}
324
```
325
326
### Multi-Process Best Practices
327
328
```java
329
// 1. Always use MULTI_PROCESS_MODE for shared data
330
MMKV sharedKv = MMKV.mmkvWithID("shared_config", MMKV.MULTI_PROCESS_MODE);
331
332
// 2. Use locking for critical sections
333
sharedKv.lock();
334
try {
335
// Atomic read-modify-write operations
336
int counter = sharedKv.decodeInt("counter", 0);
337
sharedKv.encode("counter", counter + 1);
338
} finally {
339
sharedKv.unlock();
340
}
341
342
// 3. Monitor content changes from other processes
343
MMKV.registerContentChangeNotify(mmapID -> {
344
// Refresh data when other processes make changes
345
refreshLocalCache();
346
});
347
348
// 4. Use try-lock for non-critical operations
349
if (sharedKv.tryLock()) {
350
try {
351
sharedKv.encode("last_ping", System.currentTimeMillis());
352
} finally {
353
sharedKv.unlock();
354
}
355
}
356
357
// 5. Separate single-process and multi-process data
358
MMKV localKv = MMKV.mmkvWithID("local_cache", MMKV.SINGLE_PROCESS_MODE); // Faster
359
MMKV sharedKv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE); // Synchronized
360
```
361
362
## Types
363
364
```java { .api }
365
public interface MMKVContentChangeNotification {
366
/**
367
* Inter-process content change notification.
368
* Triggered by any method call, such as getXXX() or setXXX() or checkContentChangedByOuterProcess().
369
* @param mmapID The unique ID of the changed MMKV instance
370
*/
371
void onContentChangedByOuterProcess(String mmapID);
372
}
373
374
public final class ParcelableMMKV implements Parcelable {
375
public ParcelableMMKV(MMKV mmkv);
376
public MMKV toMMKV();
377
public int describeContents();
378
public void writeToParcel(Parcel dest, int flags);
379
public static final Creator<ParcelableMMKV> CREATOR;
380
}
381
```
382
383
## Constants
384
385
```java { .api }
386
public static final int SINGLE_PROCESS_MODE = 1 << 0; // Single-process mode (default)
387
public static final int MULTI_PROCESS_MODE = 1 << 1; // Multi-process mode
388
public static final int READ_ONLY_MODE = 1 << 5; // Read-only mode
389
```