High-performance mobile key-value storage framework with memory mapping, encryption, and multi-process support for Android applications.
—
Namespace functionality for organizing MMKV instances with custom root directories, providing data isolation and organizational capabilities.
Create and manage MMKV namespaces with custom root directories for better data organization.
/**
* Create a NameSpace with custom root directory.
* @param dir The customize root directory of the NameSpace
* @return A NameSpace instance with custom root dir
* @throws RuntimeException if there's a runtime error
*/
public static NameSpace nameSpace(String dir);
/**
* Get the default NameSpace using the global MMKV root directory.
* @return The default NameSpace instance
* @throws RuntimeException if there's a runtime error
*/
public static NameSpace defaultNameSpace();
/**
* Get the root directory of this NameSpace.
* @return The root folder path of this NameSpace
*/
public String getRootDir();Usage Example:
import com.tencent.mmkv.MMKV;
import com.tencent.mmkv.NameSpace;
public class NameSpaceExample {
public void demonstrateNameSpaces(Context context) {
// Create custom namespaces for different data types
File userDataDir = new File(context.getFilesDir(), "user_data");
File cacheDir = new File(context.getCacheDir(), "mmkv_cache");
File configDir = new File(context.getFilesDir(), "app_config");
// Ensure directories exist
userDataDir.mkdirs();
cacheDir.mkdirs();
configDir.mkdirs();
// Create namespaces
NameSpace userNameSpace = MMKV.nameSpace(userDataDir.getAbsolutePath());
NameSpace cacheNameSpace = MMKV.nameSpace(cacheDir.getAbsolutePath());
NameSpace configNameSpace = MMKV.nameSpace(configDir.getAbsolutePath());
NameSpace defaultNameSpace = MMKV.defaultNameSpace();
// Verify namespace directories
Log.d("MMKV", "User namespace root: " + userNameSpace.getRootDir());
Log.d("MMKV", "Cache namespace root: " + cacheNameSpace.getRootDir());
Log.d("MMKV", "Config namespace root: " + configNameSpace.getRootDir());
Log.d("MMKV", "Default namespace root: " + defaultNameSpace.getRootDir());
}
}Create MMKV instances within specific namespaces for organized data storage.
/**
* Create an MMKV instance with unique ID in this namespace (single-process mode).
* @param mmapID The unique ID of the MMKV instance
* @return The MMKV instance in this namespace
* @throws RuntimeException if there's a runtime error
*/
public MMKV mmkvWithID(String mmapID);
/**
* Create an MMKV instance in single-process or multi-process mode.
* @param mmapID The unique ID of the MMKV instance
* @param mode The process mode (SINGLE_PROCESS_MODE or MULTI_PROCESS_MODE)
* @return The MMKV instance in this namespace
* @throws RuntimeException if there's a runtime error
*/
public MMKV mmkvWithID(String mmapID, int mode);
/**
* Create an MMKV instance with expected capacity.
* @param mmapID The unique ID of the MMKV instance
* @param mode The process mode
* @param expectedCapacity The file size expected when opening or creating file
* @return The MMKV instance in this namespace
* @throws RuntimeException if there's a runtime error
*/
public MMKV mmkvWithID(String mmapID, int mode, long expectedCapacity);
/**
* Create an MMKV instance with encryption key.
* @param mmapID The unique ID of the MMKV instance
* @param mode The process mode
* @param cryptKey The encryption key (no more than 16 bytes)
* @return The MMKV instance in this namespace
* @throws RuntimeException if there's a runtime error
*/
public MMKV mmkvWithID(String mmapID, int mode, String cryptKey);
/**
* Create an MMKV instance with all customize settings.
* @param mmapID The unique ID of the MMKV instance
* @param mode The process mode
* @param cryptKey The encryption key
* @param expectedCapacity The file size expected
* @return The MMKV instance in this namespace
* @throws RuntimeException if there's a runtime error
*/
public MMKV mmkvWithID(String mmapID, int mode, String cryptKey, long expectedCapacity);Usage Example:
public class NameSpaceInstanceExample {
private NameSpace userNameSpace;
private NameSpace cacheNameSpace;
private NameSpace configNameSpace;
public void setupNameSpaces(Context context) {
// Create organized directory structure
File baseDir = context.getFilesDir();
userNameSpace = MMKV.nameSpace(new File(baseDir, "users").getAbsolutePath());
cacheNameSpace = MMKV.nameSpace(new File(baseDir, "cache").getAbsolutePath());
configNameSpace = MMKV.nameSpace(new File(baseDir, "config").getAbsolutePath());
}
public void demonstrateOrganizedStorage() {
// User data in user namespace
MMKV userProfile = userNameSpace.mmkvWithID("profile");
MMKV userSettings = userNameSpace.mmkvWithID("settings");
MMKV userHistory = userNameSpace.mmkvWithID("history", MMKV.SINGLE_PROCESS_MODE, 1024 * 1024);
// Cache data in cache namespace (temporary, can be cleared)
MMKV imageCache = cacheNameSpace.mmkvWithID("images");
MMKV apiCache = cacheNameSpace.mmkvWithID("api_responses", MMKV.SINGLE_PROCESS_MODE, 2 * 1024 * 1024);
MMKV tempData = cacheNameSpace.mmkvWithID("temp", MMKV.SINGLE_PROCESS_MODE);
// Configuration in config namespace (encrypted for security)
MMKV appConfig = configNameSpace.mmkvWithID("app", MMKV.SINGLE_PROCESS_MODE, "config-key");
MMKV serverConfig = configNameSpace.mmkvWithID("server", MMKV.MULTI_PROCESS_MODE, "server-key");
// Store data in organized manner
storeUserData(userProfile, userSettings, userHistory);
storeCacheData(imageCache, apiCache, tempData);
storeConfigData(appConfig, serverConfig);
}
private void storeUserData(MMKV profile, MMKV settings, MMKV history) {
// User profile data
profile.encode("user_id", 12345);
profile.encode("username", "john_doe");
profile.encode("email", "john@example.com");
// User settings
settings.encode("theme", "dark");
settings.encode("notifications", true);
settings.encode("language", "en");
// User history
history.encode("last_login", System.currentTimeMillis());
history.encode("session_count", history.decodeInt("session_count", 0) + 1);
Log.d("MMKV", "User data stored in user namespace");
}
private void storeCacheData(MMKV imageCache, MMKV apiCache, MMKV tempData) {
// Image cache
imageCache.encode("profile_image_url", "https://example.com/profile.jpg");
imageCache.encode("cache_timestamp", System.currentTimeMillis());
// API cache
apiCache.encode("user_data_response", "{\"id\": 123, \"name\": \"John\"}");
apiCache.encode("api_cache_expiry", System.currentTimeMillis() + 3600000); // 1 hour
// Temporary data
tempData.encode("temp_session_id", "temp_" + System.currentTimeMillis());
Log.d("MMKV", "Cache data stored in cache namespace");
}
private void storeConfigData(MMKV appConfig, MMKV serverConfig) {
// App configuration (encrypted)
appConfig.encode("api_key", "secret-api-key-12345");
appConfig.encode("debug_mode", BuildConfig.DEBUG);
appConfig.encode("app_version", BuildConfig.VERSION_NAME);
// Server configuration (encrypted, multi-process for service access)
serverConfig.encode("server_url", "https://api.example.com");
serverConfig.encode("timeout_seconds", 30);
serverConfig.encode("retry_count", 3);
Log.d("MMKV", "Config data stored in config namespace (encrypted)");
}
}Perform file operations within specific namespaces.
/**
* Backup one MMKV instance within this namespace to destination directory.
* @param mmapID The MMKV ID to backup
* @param dstDir The backup destination directory
* @return True if backup successful
*/
public boolean backupOneToDirectory(String mmapID, String dstDir);
/**
* Restore one MMKV instance within this namespace from source directory.
* @param mmapID The MMKV ID to restore
* @param srcDir The restore source directory
* @return True if restore successful
*/
public boolean restoreOneMMKVFromDirectory(String mmapID, String srcDir);
/**
* Check whether the MMKV file is valid within this namespace.
* @param mmapID The unique ID of the MMKV instance
* @return True if file is valid
*/
public boolean isFileValid(String mmapID);
/**
* Remove the storage of the MMKV within this namespace.
* @param mmapID The unique ID of the MMKV instance
* @return True if removal successful
*/
public boolean removeStorage(String mmapID);
/**
* Check existence of the MMKV file within this namespace.
* @param mmapID The unique ID of the MMKV instance
* @return True if file exists
*/
public boolean checkExist(String mmapID);Usage Example:
public class NameSpaceFileOperationsExample {
public void demonstrateNameSpaceFileOps(Context context) {
// Setup namespaces
NameSpace userNameSpace = MMKV.nameSpace(
new File(context.getFilesDir(), "users").getAbsolutePath());
NameSpace backupNameSpace = MMKV.nameSpace(
new File(context.getExternalFilesDir(null), "backup").getAbsolutePath());
// Create some data in user namespace
MMKV userProfile = userNameSpace.mmkvWithID("profile");
userProfile.encode("name", "John Doe");
userProfile.encode("age", 30);
userProfile.encode("email", "john@example.com");
MMKV userSettings = userNameSpace.mmkvWithID("settings");
userSettings.encode("theme", "dark");
userSettings.encode("notifications", true);
// Check file existence and validity within namespace
boolean profileExists = userNameSpace.checkExist("profile");
boolean profileValid = userNameSpace.isFileValid("profile");
boolean settingsExists = userNameSpace.checkExist("settings");
boolean settingsValid = userNameSpace.isFileValid("settings");
Log.d("MMKV", String.format("Profile - exists: %b, valid: %b", profileExists, profileValid));
Log.d("MMKV", String.format("Settings - exists: %b, valid: %b", settingsExists, settingsValid));
// Backup files from user namespace
File backupDir = new File(context.getExternalFilesDir(null), "user_backup");
backupDir.mkdirs();
boolean profileBackup = userNameSpace.backupOneToDirectory("profile", backupDir.getAbsolutePath());
boolean settingsBackup = userNameSpace.backupOneToDirectory("settings", backupDir.getAbsolutePath());
Log.d("MMKV", String.format("Backup results - Profile: %b, Settings: %b",
profileBackup, settingsBackup));
// Simulate data loss and restore
userNameSpace.removeStorage("profile");
userNameSpace.removeStorage("settings");
Log.d("MMKV", "Simulated data loss - files removed");
// Restore from backup
boolean profileRestore = userNameSpace.restoreOneMMKVFromDirectory("profile", backupDir.getAbsolutePath());
boolean settingsRestore = userNameSpace.restoreOneMMKVFromDirectory("settings", backupDir.getAbsolutePath());
Log.d("MMKV", String.format("Restore results - Profile: %b, Settings: %b",
profileRestore, settingsRestore));
// Verify restored data
if (profileRestore) {
MMKV restoredProfile = userNameSpace.mmkvWithID("profile");
String name = restoredProfile.decodeString("name");
int age = restoredProfile.decodeInt("age");
Log.d("MMKV", String.format("Restored profile - Name: %s, Age: %d", name, age));
}
}
}Use namespaces to organize data for multiple users with proper isolation.
Usage Example:
public class MultiUserNameSpaceExample {
private Map<String, NameSpace> userNameSpaces;
private NameSpace sharedNameSpace;
public void setupMultiUserEnvironment(Context context) {
userNameSpaces = new HashMap<>();
// Create shared namespace for app-wide data
File sharedDir = new File(context.getFilesDir(), "shared");
sharedNameSpace = MMKV.nameSpace(sharedDir.getAbsolutePath());
Log.d("MMKV", "Multi-user environment initialized");
}
public NameSpace getUserNameSpace(Context context, String userId) {
NameSpace userNameSpace = userNameSpaces.get(userId);
if (userNameSpace == null) {
// Create user-specific namespace
File userDir = new File(context.getFilesDir(), "users/" + userId);
userDir.mkdirs();
userNameSpace = MMKV.nameSpace(userDir.getAbsolutePath());
userNameSpaces.put(userId, userNameSpace);
Log.d("MMKV", "Created namespace for user: " + userId +
" at " + userNameSpace.getRootDir());
}
return userNameSpace;
}
public void storeUserData(Context context, String userId, String username, String email) {
NameSpace userNameSpace = getUserNameSpace(context, userId);
// User-specific data
MMKV userProfile = userNameSpace.mmkvWithID("profile");
userProfile.encode("user_id", userId);
userProfile.encode("username", username);
userProfile.encode("email", email);
userProfile.encode("created_at", System.currentTimeMillis());
MMKV userSettings = userNameSpace.mmkvWithID("settings");
userSettings.encode("theme", "default");
userSettings.encode("language", "en");
userSettings.encode("notifications", true);
MMKV userCache = userNameSpace.mmkvWithID("cache");
userCache.encode("last_sync", System.currentTimeMillis());
// Update shared data (user list)
MMKV sharedUserList = sharedNameSpace.mmkvWithID("user_list");
Set<String> existingUsers = sharedUserList.decodeStringSet("active_users", new HashSet<>());
existingUsers.add(userId);
sharedUserList.encode("active_users", existingUsers);
Log.d("MMKV", String.format("Stored data for user %s (%s)", userId, username));
}
public void switchUser(Context context, String fromUserId, String toUserId) {
// Clear current user cache if needed
if (fromUserId != null) {
NameSpace fromNameSpace = getUserNameSpace(context, fromUserId);
MMKV fromCache = fromNameSpace.mmkvWithID("cache");
fromCache.clearAllWithKeepingSpace(); // Clear cache but keep file
Log.d("MMKV", "Cleared cache for user: " + fromUserId);
}
// Load new user data
NameSpace toNameSpace = getUserNameSpace(context, toUserId);
MMKV toProfile = toNameSpace.mmkvWithID("profile");
MMKV toSettings = toNameSpace.mmkvWithID("settings");
String username = toProfile.decodeString("username", "Unknown");
String theme = toSettings.decodeString("theme", "default");
boolean notifications = toSettings.decodeBool("notifications", true);
Log.d("MMKV", String.format("Switched to user %s: theme=%s, notifications=%b",
username, theme, notifications));
}
public void deleteUser(Context context, String userId) {
NameSpace userNameSpace = userNameSpaces.get(userId);
if (userNameSpace != null) {
// Remove all user data files
userNameSpace.removeStorage("profile");
userNameSpace.removeStorage("settings");
userNameSpace.removeStorage("cache");
// Remove from active users list
MMKV sharedUserList = sharedNameSpace.mmkvWithID("user_list");
Set<String> activeUsers = sharedUserList.decodeStringSet("active_users", new HashSet<>());
activeUsers.remove(userId);
sharedUserList.encode("active_users", activeUsers);
// Remove from cache
userNameSpaces.remove(userId);
// Delete user directory
File userDir = new File(userNameSpace.getRootDir());
deleteDirectory(userDir);
Log.d("MMKV", "Deleted all data for user: " + userId);
}
}
public void backupAllUsers(Context context) {
File backupRoot = new File(context.getExternalFilesDir(null), "user_backups");
backupRoot.mkdirs();
// Backup shared data
File sharedBackup = new File(backupRoot, "shared");
sharedBackup.mkdirs();
sharedNameSpace.backupOneToDirectory("user_list", sharedBackup.getAbsolutePath());
// Backup each user
for (Map.Entry<String, NameSpace> entry : userNameSpaces.entrySet()) {
String userId = entry.getKey();
NameSpace userNameSpace = entry.getValue();
File userBackup = new File(backupRoot, "user_" + userId);
userBackup.mkdirs();
userNameSpace.backupOneToDirectory("profile", userBackup.getAbsolutePath());
userNameSpace.backupOneToDirectory("settings", userBackup.getAbsolutePath());
// Don't backup cache as it's temporary
Log.d("MMKV", "Backed up user: " + userId);
}
Log.d("MMKV", "All user data backed up to: " + backupRoot.getAbsolutePath());
}
private void deleteDirectory(File dir) {
if (dir.exists()) {
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
deleteDirectory(file);
} else {
file.delete();
}
}
}
dir.delete();
}
}
}Guidelines for effective namespace usage and organization.
Usage Example:
public class NameSpaceBestPractices {
/**
* Recommended namespace organization for a typical Android app.
*/
public static class AppNameSpaceManager {
private final Context context;
private final NameSpace userNameSpace;
private final NameSpace cacheNameSpace;
private final NameSpace configNameSpace;
private final NameSpace logNameSpace;
public AppNameSpaceManager(Context context) {
this.context = context.getApplicationContext();
// Create well-organized directory structure
File baseDir = context.getFilesDir();
// User data - persistent, important data
this.userNameSpace = MMKV.nameSpace(
new File(baseDir, "user").getAbsolutePath());
// Cache data - temporary, can be cleared
this.cacheNameSpace = MMKV.nameSpace(
context.getCacheDir().getAbsolutePath() + "/mmkv");
// Configuration - encrypted, critical settings
this.configNameSpace = MMKV.nameSpace(
new File(baseDir, "config").getAbsolutePath());
// Logs - for debugging and analytics
this.logNameSpace = MMKV.nameSpace(
new File(baseDir, "logs").getAbsolutePath());
}
// User data methods
public MMKV getUserProfile() {
return userNameSpace.mmkvWithID("profile");
}
public MMKV getUserSettings() {
return userNameSpace.mmkvWithID("settings");
}
public MMKV getUserHistory() {
return userNameSpace.mmkvWithID("history", MMKV.SINGLE_PROCESS_MODE, 2 * 1024 * 1024);
}
// Cache data methods
public MMKV getImageCache() {
return cacheNameSpace.mmkvWithID("images", MMKV.SINGLE_PROCESS_MODE, 10 * 1024 * 1024);
}
public MMKV getApiCache() {
return cacheNameSpace.mmkvWithID("api", MMKV.SINGLE_PROCESS_MODE, 5 * 1024 * 1024);
}
public MMKV getTempStorage() {
return cacheNameSpace.mmkvWithID("temp");
}
// Configuration methods (encrypted)
public MMKV getAppConfig() {
return configNameSpace.mmkvWithID("app", MMKV.SINGLE_PROCESS_MODE, generateConfigKey());
}
public MMKV getServerConfig() {
return configNameSpace.mmkvWithID("server", MMKV.MULTI_PROCESS_MODE, generateServerKey());
}
// Logging methods
public MMKV getEventLog() {
return logNameSpace.mmkvWithID("events", MMKV.SINGLE_PROCESS_MODE, 1024 * 1024);
}
public MMKV getErrorLog() {
return logNameSpace.mmkvWithID("errors", MMKV.SINGLE_PROCESS_MODE, 512 * 1024);
}
// Maintenance methods
public void clearAllCaches() {
cacheNameSpace.mmkvWithID("images").clearAllWithKeepingSpace();
cacheNameSpace.mmkvWithID("api").clearAllWithKeepingSpace();
cacheNameSpace.mmkvWithID("temp").clearAll();
Log.d("MMKV", "All caches cleared");
}
public void rotateLogs() {
// Archive current logs and create new ones
File logBackup = new File(context.getFilesDir(), "log_archive");
logBackup.mkdirs();
logNameSpace.backupOneToDirectory("events", logBackup.getAbsolutePath());
logNameSpace.backupOneToDirectory("errors", logBackup.getAbsolutePath());
// Clear current logs
logNameSpace.mmkvWithID("events").clearAll();
logNameSpace.mmkvWithID("errors").clearAll();
Log.d("MMKV", "Logs rotated and archived");
}
public void performMaintenance() {
// Trim cache files to reclaim space
cacheNameSpace.mmkvWithID("images").trim();
cacheNameSpace.mmkvWithID("api").trim();
// Rotate logs if they're too large
MMKV eventLog = logNameSpace.mmkvWithID("events");
if (eventLog.totalSize() > 5 * 1024 * 1024) { // 5MB
rotateLogs();
}
Log.d("MMKV", "Namespace maintenance completed");
}
private String generateConfigKey() {
// Generate app-specific encryption key
return "app_config_" + context.getPackageName().hashCode();
}
private String generateServerKey() {
// Generate server-specific encryption key
return "server_config_" + BuildConfig.APPLICATION_ID.hashCode();
}
}
/**
* Usage example of the namespace manager.
*/
public void demonstrateNameSpaceManager(Context context) {
AppNameSpaceManager nsManager = new AppNameSpaceManager(context);
// Store user data
MMKV userProfile = nsManager.getUserProfile();
userProfile.encode("user_id", 12345);
userProfile.encode("name", "John Doe");
MMKV userSettings = nsManager.getUserSettings();
userSettings.encode("theme", "dark");
userSettings.encode("notifications", true);
// Store configuration (encrypted)
MMKV appConfig = nsManager.getAppConfig();
appConfig.encode("api_endpoint", "https://api.example.com");
appConfig.encode("app_secret", "secret-key-12345");
// Use cache
MMKV imageCache = nsManager.getImageCache();
imageCache.encode("profile_image", "cached_image_data");
// Log events
MMKV eventLog = nsManager.getEventLog();
eventLog.encode("app_started", System.currentTimeMillis());
eventLog.encode("user_login", "john_doe");
// Perform maintenance
nsManager.performMaintenance();
Log.d("MMKV", "Namespace manager demonstration completed");
}
}Install with Tessl CLI
npx tessl i tessl/maven-com-tencent--mmkv