0
# Advanced Features
1
2
MMKV provides advanced functionality including encryption, key expiration, backup/restore capabilities, and performance optimizations for sophisticated use cases.
3
4
## Capabilities
5
6
### Encryption
7
8
MMKV supports AES encryption with custom keys up to 16 bytes for securing sensitive data.
9
10
```java { .api }
11
/**
12
* Get the encryption key of the MMKV instance
13
* @return The encryption key (no more than 16 bytes), or null if not encrypted
14
*/
15
String cryptKey();
16
17
/**
18
* Transform plain text into encrypted text, or vice versa by passing a null encryption key.
19
* You can also change existing crypt key with a different cryptKey.
20
* @param cryptKey The new encryption key (no more than 16 bytes)
21
* @return True if success, otherwise False
22
*/
23
boolean reKey(String cryptKey);
24
25
/**
26
* Just reset the encryption key (will not encrypt or decrypt anything).
27
* Usually you should call this method after another process has reKey() the multi-process MMKV instance.
28
* @param cryptKey The new encryption key (no more than 16 bytes)
29
*/
30
void checkReSetCryptKey(String cryptKey);
31
```
32
33
**Usage Examples:**
34
35
```java
36
// Create encrypted instance
37
MMKV secureKv = MMKV.mmkvWithID("secure_data", MMKV.SINGLE_PROCESS_MODE, "my-secret-key");
38
39
// Check current encryption key
40
String currentKey = secureKv.cryptKey();
41
if (currentKey != null) {
42
Log.d("MMKV", "Instance is encrypted");
43
}
44
45
// Change encryption key
46
boolean success = secureKv.reKey("new-secret-key");
47
if (success) {
48
Log.d("MMKV", "Encryption key changed successfully");
49
}
50
51
// Remove encryption (convert to plain text)
52
boolean decrypted = secureKv.reKey(null);
53
54
// In multi-process scenario, sync key change
55
secureKv.checkReSetCryptKey("new-key-from-other-process");
56
```
57
58
### Key Expiration
59
60
MMKV supports automatic key expiration with configurable durations to implement time-based data cleanup.
61
62
```java { .api }
63
/**
64
* Enable auto key expiration. This is a upgrade operation, the file format will change.
65
* And the file won't be accessed correctly by older version (v1.2.16) of MMKV.
66
* NOTICE: enableCompareBeforeSet will be invalid when Expiration is on
67
* @param expireDurationInSecond the expire duration for all keys, 0 means no default duration
68
* @return True if successful, False otherwise
69
*/
70
boolean enableAutoKeyExpire(int expireDurationInSecond);
71
72
/**
73
* Disable auto key expiration. This is a downgrade operation.
74
* @return True if successful, False otherwise
75
*/
76
boolean disableAutoKeyExpire();
77
```
78
79
**Usage Examples:**
80
81
```java
82
MMKV kv = MMKV.mmkvWithID("expiring_data");
83
84
// Enable expiration with 1 hour default for all keys
85
boolean enabled = kv.enableAutoKeyExpire(MMKV.ExpireInHour);
86
if (enabled) {
87
// All new keys will expire in 1 hour by default
88
kv.encode("default_expire", "will expire in 1 hour");
89
90
// Override default expiration for specific keys
91
kv.encode("custom_expire", "will expire in 10 minutes", 10 * 60);
92
93
// Never expire specific keys
94
kv.encode("permanent", "never expires", MMKV.ExpireNever);
95
}
96
97
// Check expired vs non-expired keys
98
String[] allKeys = kv.allKeys(); // All keys including expired
99
String[] activeKeys = kv.allNonExpireKeys(); // Only non-expired keys
100
long totalCount = kv.count(); // All keys count
101
long activeCount = kv.countNonExpiredKeys(); // Non-expired keys count
102
103
// Disable expiration
104
boolean disabled = kv.disableAutoKeyExpire();
105
```
106
107
### Performance Optimizations
108
109
MMKV provides several performance optimization features for specific use cases.
110
111
```java { .api }
112
/**
113
* Enable data compare before set, for better performance.
114
* If data for key seldom changes, use it.
115
* When encryption or expiration is on, compare-before-set will be invalid.
116
*/
117
void enableCompareBeforeSet();
118
119
/**
120
* Disable data compare before set
121
* disabled at default
122
*/
123
void disableCompareBeforeSet();
124
```
125
126
**Usage Examples:**
127
128
```java
129
MMKV kv = MMKV.mmkvWithID("optimized_storage");
130
131
// Enable compare-before-set for better performance when data rarely changes
132
// Note: Invalid when encryption or expiration is enabled
133
kv.enableCompareBeforeSet();
134
135
// Now MMKV will compare new data with existing data before writing
136
kv.encode("stable_config", configData); // Only writes if data actually changed
137
138
// Disable optimization if data changes frequently
139
kv.disableCompareBeforeSet();
140
```
141
142
### Backup and Restore
143
144
MMKV provides built-in backup and restore functionality for data migration and recovery.
145
146
```java { .api }
147
/**
148
* Backup one MMKV instance to dstDir
149
* @param mmapID the MMKV ID to backup
150
* @param dstDir the backup destination directory
151
* @param rootPath the customize root path of the MMKV, if null then backup from the root dir of MMKV
152
* @return True if backup successful, False otherwise
153
*/
154
static boolean backupOneToDirectory(String mmapID, String dstDir, String rootPath);
155
156
/**
157
* Restore one MMKV instance from srcDir
158
* @param mmapID the MMKV ID to restore
159
* @param srcDir the restore source directory
160
* @param rootPath the customize root path of the MMKV, if null then restore to the root dir of MMKV
161
* @return True if restore successful, False otherwise
162
*/
163
static boolean restoreOneMMKVFromDirectory(String mmapID, String srcDir, String rootPath);
164
165
/**
166
* Backup all MMKV instance from default root dir to dstDir
167
* @param dstDir the backup destination directory
168
* @return count of MMKV successfully backuped
169
*/
170
static long backupAllToDirectory(String dstDir);
171
172
/**
173
* Restore all MMKV instance from srcDir to default root dir
174
* @param srcDir the restore source directory
175
* @return count of MMKV successfully restored
176
*/
177
static long restoreAllFromDirectory(String srcDir);
178
179
/**
180
* Import all key-value items from another MMKV instance
181
* @param src The source MMKV instance to import from
182
* @return count of items imported
183
*/
184
long importFrom(MMKV src);
185
```
186
187
**Usage Examples:**
188
189
```java
190
// Backup specific instance
191
File backupDir = new File(getExternalFilesDir(null), "mmkv_backup");
192
backupDir.mkdirs();
193
194
boolean backupSuccess = MMKV.backupOneToDirectory(
195
"user_data",
196
backupDir.getAbsolutePath(),
197
null
198
);
199
200
if (backupSuccess) {
201
Log.d("MMKV", "Backup completed successfully");
202
}
203
204
// Backup all instances
205
long backedUpCount = MMKV.backupAllToDirectory(backupDir.getAbsolutePath());
206
Log.d("MMKV", "Backed up " + backedUpCount + " instances");
207
208
// Restore specific instance
209
boolean restoreSuccess = MMKV.restoreOneMMKVFromDirectory(
210
"user_data",
211
backupDir.getAbsolutePath(),
212
null
213
);
214
215
// Restore all instances
216
long restoredCount = MMKV.restoreAllFromDirectory(backupDir.getAbsolutePath());
217
Log.d("MMKV", "Restored " + restoredCount + " instances");
218
219
// Import from another MMKV instance
220
MMKV sourceKv = MMKV.mmkvWithID("source_data");
221
MMKV targetKv = MMKV.mmkvWithID("target_data");
222
long importedCount = targetKv.importFrom(sourceKv);
223
Log.d("MMKV", "Imported " + importedCount + " items");
224
```
225
226
### Storage Management
227
228
Advanced storage management capabilities for monitoring and optimizing storage usage.
229
230
```java { .api }
231
/**
232
* Get the size of the underlying file. Align to the disk block size, typically 4K for an Android device.
233
* @return Total file size in bytes
234
*/
235
long totalSize();
236
237
/**
238
* Get the actual used size of the MMKV instance.
239
* This size might increase and decrease as MMKV doing insertion and full write back.
240
* @return Actual used size in bytes
241
*/
242
long actualSize();
243
244
/**
245
* The totalSize() of an MMKV instance won't reduce after deleting key-values,
246
* call this method after lots of deleting if you care about disk usage.
247
* Note that clearAll() has a similar effect.
248
*/
249
void trim();
250
251
/**
252
* Clear all the key-values inside the MMKV instance.
253
* The data file will be trimmed down to pageSize, and some sync operations will be called
254
* If you do not want to trim the file, use clearAllWithKeepingSpace() instead for better performance
255
*/
256
void clearAll();
257
258
/**
259
* Faster clearAll() implementation
260
* The file size is kept as previous for later use
261
*/
262
void clearAllWithKeepingSpace();
263
264
/**
265
* Call this method if the MMKV instance is no longer needed in the near future.
266
* Any subsequent call to any MMKV instances with the same ID is undefined behavior.
267
*/
268
void close();
269
270
/**
271
* Clear memory cache of the MMKV instance.
272
* You can call it on memory warning.
273
* Any subsequent call to the MMKV instance will trigger all key-values loading from the file again.
274
*/
275
void clearMemoryCache();
276
```
277
278
**Usage Examples:**
279
280
```java
281
MMKV kv = MMKV.mmkvWithID("large_storage");
282
283
// Monitor storage usage
284
long totalBytes = kv.totalSize(); // File size on disk
285
long usedBytes = kv.actualSize(); // Actually used space
286
long wastedBytes = totalBytes - usedBytes;
287
288
Log.d("MMKV", "Total: " + totalBytes + ", Used: " + usedBytes + ", Wasted: " + wastedBytes);
289
290
// Optimize storage after many deletions
291
if (wastedBytes > totalBytes * 0.5) { // More than 50% wasted space
292
kv.trim(); // Reclaim unused space
293
}
294
295
// Clear all data with trimming
296
kv.clearAll();
297
298
// Clear all data but keep file size for performance
299
kv.clearAllWithKeepingSpace();
300
301
// Memory management
302
kv.clearMemoryCache(); // Free memory cache
303
304
// Cleanup when done
305
kv.close(); // Close instance when no longer needed
306
```
307
308
### File Validation and Utilities
309
310
Utility methods for checking file status and managing MMKV storage files.
311
312
```java { .api }
313
/**
314
* Check whether the MMKV file is valid or not.
315
* Note: Don't use this to check the existence of the instance, the result is undefined on nonexistent files.
316
* @param mmapID The unique ID of the MMKV instance
317
* @return True if the file is valid, False otherwise
318
*/
319
static boolean isFileValid(String mmapID);
320
321
/**
322
* Check whether the MMKV file is valid or not on customize folder.
323
* @param mmapID The unique ID of the MMKV instance
324
* @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv
325
* @return True if the file is valid, False otherwise
326
*/
327
static boolean isFileValid(String mmapID, String rootPath);
328
329
/**
330
* Remove the storage of the MMKV, including the data file & meta file (.crc)
331
* Note: the existing instance (if any) will be closed & destroyed
332
* @param mmapID The unique ID of the MMKV instance
333
* @return True if removal successful, False otherwise
334
*/
335
static boolean removeStorage(String mmapID);
336
337
/**
338
* Remove the storage of the MMKV, including the data file & meta file (.crc)
339
* Note: the existing instance (if any) will be closed & destroyed
340
* @param mmapID The unique ID of the MMKV instance
341
* @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv
342
* @return True if removal successful, False otherwise
343
*/
344
static boolean removeStorage(String mmapID, String rootPath);
345
346
/**
347
* Check existence of the MMKV file
348
* @param mmapID The unique ID of the MMKV instance
349
* @return True if the file exists, False otherwise
350
*/
351
static boolean checkExist(String mmapID);
352
353
/**
354
* Check existence of the MMKV file
355
* @param mmapID The unique ID of the MMKV instance
356
* @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv
357
* @return True if the file exists, False otherwise
358
*/
359
static boolean checkExist(String mmapID, String rootPath);
360
361
/**
362
* Get the device's memory page size
363
* @return Memory page size in bytes
364
*/
365
static int pageSize();
366
367
/**
368
* Get the version of MMKV
369
* @return Version string
370
*/
371
static String version();
372
```
373
374
**Usage Examples:**
375
376
```java
377
// Check if MMKV files are valid before using
378
if (MMKV.isFileValid("user_data")) {
379
MMKV kv = MMKV.mmkvWithID("user_data");
380
// Use normally
381
} else {
382
Log.w("MMKV", "Invalid MMKV file, may need recovery");
383
}
384
385
// Check file existence
386
if (MMKV.checkExist("temp_data")) {
387
// File exists, can open
388
} else {
389
// File doesn't exist, will be created on first use
390
}
391
392
// Remove storage files
393
boolean removed = MMKV.removeStorage("old_data");
394
if (removed) {
395
Log.d("MMKV", "Old storage removed successfully");
396
}
397
398
// System information
399
int pageSize = MMKV.pageSize(); // Usually 4096 on Android
400
String version = MMKV.version(); // e.g., "2.2.2"
401
Log.d("MMKV", "Page size: " + pageSize + ", Version: " + version);
402
```
403
404
### Native Buffer Operations
405
406
Direct native memory operations for advanced use cases requiring high performance.
407
408
```java { .api }
409
/**
410
* Create an native buffer, whose underlying memory can be directly transferred to another JNI method.
411
* Avoiding unnecessary JNI boxing and unboxing.
412
* An NativeBuffer must be manually destroyed to avoid memory leak.
413
* @param size The size of the underlying memory
414
* @return NativeBuffer instance, or null if allocation failed
415
*/
416
static NativeBuffer createNativeBuffer(int size);
417
418
/**
419
* Destroy the native buffer. An NativeBuffer must be manually destroy to avoid memory leak.
420
* @param buffer The native buffer to destroy
421
*/
422
static void destroyNativeBuffer(NativeBuffer buffer);
423
424
/**
425
* Write the value of the key to the native buffer.
426
* @param key The key to read
427
* @param buffer The native buffer to write to
428
* @return The size written. Return -1 on any error
429
*/
430
int writeValueToNativeBuffer(String key, NativeBuffer buffer);
431
```
432
433
**Usage Examples:**
434
435
```java
436
// Create native buffer for high-performance operations
437
NativeBuffer buffer = MMKV.createNativeBuffer(1024);
438
if (buffer != null) {
439
try {
440
MMKV kv = MMKV.mmkvWithID("high_perf");
441
442
// Write value directly to native buffer
443
int bytesWritten = kv.writeValueToNativeBuffer("large_data", buffer);
444
if (bytesWritten > 0) {
445
// Pass buffer to other JNI methods for processing
446
// processNativeBuffer(buffer.pointer, buffer.size);
447
}
448
} finally {
449
// Always destroy buffer to prevent memory leaks
450
MMKV.destroyNativeBuffer(buffer);
451
}
452
}
453
```
454
455
## Types
456
457
```java { .api }
458
/**
459
* A native memory wrapper, whose underlying memory can be passed to another JNI method directly.
460
* Avoiding unnecessary JNI boxing and unboxing.
461
* Must be destroy manually.
462
*/
463
class NativeBuffer {
464
public long pointer; // Native memory pointer
465
public int size; // Buffer size
466
467
NativeBuffer(long ptr, int length);
468
}
469
```