CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-tencent--mmkv

High-performance mobile key-value storage framework with memory mapping, encryption, and multi-process support for Android applications.

Pending
Overview
Eval results
Files

namespace.mddocs/

Namespace Support

Namespace functionality for organizing MMKV instances with custom root directories, providing data isolation and organizational capabilities.

Capabilities

Namespace Creation

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());
    }
}

Instance Creation within Namespaces

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)");
    }
}

Namespace File Operations

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));
        }
    }
}

Multi-User Data Organization

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();
        }
    }
}

Namespace Best Practices

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");
    }
}

Important Notes

  1. Directory Management: Namespaces require directories to exist before creation
  2. Data Isolation: Each namespace maintains completely separate data files
  3. Path Consistency: Always use absolute paths for namespace directories
  4. Backup/Restore: Namespace-aware backup operations only affect files within that namespace
  5. Memory Usage: Each namespace may have its own memory mappings, consider resource usage
  6. Organization: Use meaningful directory names that reflect data purpose (user, cache, config, etc.)
  7. Security: Apply appropriate permissions to namespace directories based on data sensitivity
  8. Cleanup: Remove unused namespaces and their directories when no longer needed

Install with Tessl CLI

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

docs

data-management.md

data-storage.md

encryption.md

index.md

initialization.md

instance-management.md

multi-process.md

namespace.md

tile.json