dhis2_android_configure_storage
Configure local storage and database settings for the DHIS2 Android app. Define storage type, encryption level, cache strategy, and purge policies to optimize data management and performance.
Instructions
Set up local storage and database configuration for DHIS2 Android app
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| cacheStrategy | No | ||
| encryptionLevel | No | Database encryption level | |
| purgePolicy | No | ||
| storageType | Yes | Local database technology |
Implementation Reference
- src/index.ts:1273-1283 (handler)Main tool handler that receives arguments, calls generateStorageConfiguration, and returns the generated configuration as text content.case 'dhis2_android_configure_storage': const storageArgs = args as any; const storageConfig = generateStorageConfiguration(storageArgs); return { content: [ { type: 'text', text: storageConfig, }, ], };
- src/android-generators.ts:1186-1242 (helper)Core generator function that produces detailed Android storage configuration code and instructions based on input parameters like storageType, encryptionLevel, etc.export function generateStorageConfiguration(args: any): string { const { storageType, encryptionLevel, cacheStrategy, purgePolicy } = args; return `# DHIS2 Android Storage Configuration ## Database Technology: ${storageType.toUpperCase()} ## Encryption Level: ${encryptionLevel.toUpperCase()} ${generateDatabaseConfiguration(storageType, encryptionLevel)} ${cacheStrategy ? generateCacheStrategy(cacheStrategy) : ''} ${purgePolicy?.enabled ? generatePurgePolicy(purgePolicy) : ''} ## Usage Examples \`\`\`kotlin @Database( entities = [DataElement::class, OrganisationUnit::class, Event::class], version = 1, exportSchema = false ) ${encryptionLevel !== 'none' ? '@TypeConverters(CryptoConverter::class)' : ''} abstract class DHIS2Database : RoomDatabase() { abstract fun dataElementDao(): DataElementDao abstract fun organisationUnitDao(): OrganisationUnitDao abstract fun eventDao(): EventDao companion object { @Volatile private var INSTANCE: DHIS2Database? = null fun getDatabase(context: Context): DHIS2Database { return INSTANCE ?: synchronized(this) { val instance = Room.databaseBuilder( context.applicationContext, DHIS2Database::class.java, "dhis2_database" ).apply { ${encryptionLevel !== 'none' ? 'openHelperFactory(SupportFactory(getPassphrase()))' : ''} ${cacheStrategy ? 'setQueryExecutor(Executors.newFixedThreadPool(4))' : ''} }.build() INSTANCE = instance instance } } ${encryptionLevel !== 'none' ? ` private fun getPassphrase(): ByteArray { // Generate or retrieve secure passphrase return "your-secure-passphrase".toByteArray() }` : ''} } } \`\`\` `; }
- src/permission-system.ts:158-158 (registration)Tool permission registration mapping the tool to required 'canConfigureMobile' permission.['dhis2_android_configure_storage', 'canConfigureMobile'],
- src/android-generators.ts:1244-1513 (helper)Helper function called by generateStorageConfiguration to produce specific database configuration for Room, SQLite, or Realm with encryption support.function generateDatabaseConfiguration(storageType: string, encryptionLevel: string): string { switch (storageType) { case 'room': return generateRoomConfiguration(encryptionLevel); case 'sqlite': return generateSQLiteConfiguration(encryptionLevel); case 'realm': return generateRealmConfiguration(encryptionLevel); default: return generateRoomConfiguration(encryptionLevel); } } function generateRoomConfiguration(encryptionLevel: string): string { return ` ### Room Database Configuration **Dependencies** (add to build.gradle): \`\`\`kotlin dependencies { implementation "androidx.room:room-runtime:2.6.1" implementation "androidx.room:room-ktx:2.6.1" kapt "androidx.room:room-compiler:2.6.1" ${encryptionLevel !== 'none' ? `// SQLCipher for encryption implementation "net.zetetic:android-database-sqlcipher:4.5.4" implementation "androidx.sqlite:sqlite:2.4.0"` : ''} } \`\`\` **Entity Example**: \`\`\`kotlin @Entity(tableName = "data_elements") data class DataElement( @PrimaryKey val id: String, val name: String, val shortName: String, val valueType: String, ${encryptionLevel !== 'none' ? '@Encrypted val sensitiveData: String? = null,' : ''} val lastUpdated: Long = System.currentTimeMillis() ) \`\`\` **DAO Example**: \`\`\`kotlin @Dao interface DataElementDao { @Query("SELECT * FROM data_elements WHERE id = :id") suspend fun getById(id: String): DataElement? @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(dataElement: DataElement) @Query("DELETE FROM data_elements WHERE lastUpdated < :threshold") suspend fun deleteOldRecords(threshold: Long) } \`\`\` `; } function generateSQLiteConfiguration(encryptionLevel: string): string { return ` ### SQLite Database Configuration \`\`\`kotlin class DHIS2DatabaseHelper(context: Context) : SQLiteOpenHelper( context, DATABASE_NAME, null, DATABASE_VERSION ) { override fun onCreate(db: SQLiteDatabase) { db.execSQL(CREATE_DATA_ELEMENTS_TABLE) db.execSQL(CREATE_ORG_UNITS_TABLE) db.execSQL(CREATE_EVENTS_TABLE) } override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { // Handle database upgrades when (oldVersion) { 1 -> upgradeToVersion2(db) } } companion object { private const val DATABASE_NAME = "dhis2.db" private const val DATABASE_VERSION = 1 private const val CREATE_DATA_ELEMENTS_TABLE = """ CREATE TABLE data_elements ( id TEXT PRIMARY KEY, name TEXT NOT NULL, value_type TEXT NOT NULL, last_updated INTEGER DEFAULT CURRENT_TIMESTAMP ) """ } } \`\`\` `; } function generateRealmConfiguration(encryptionLevel: string): string { return ` ### Realm Database Configuration \`\`\`kotlin class DHIS2Application : Application() { override fun onCreate() { super.onCreate() Realm.init(this) val config = RealmConfiguration.Builder() .name("dhis2.realm") .schemaVersion(1) ${encryptionLevel !== 'none' ? '.encryptionKey(getEncryptionKey())' : ''} .migration { realm, oldVersion, newVersion -> // Handle migrations } .build() Realm.setDefaultConfiguration(config) } ${encryptionLevel !== 'none' ? ` private fun getEncryptionKey(): ByteArray { // Generate 64-byte encryption key return ByteArray(64) { 0x12 } }` : ''} } open class DataElement : RealmObject() { @PrimaryKey var id: String = "" var name: String = "" var shortName: String = "" var valueType: String = "" var lastUpdated: Long = 0 } \`\`\` `; } function generateCacheStrategy(cacheStrategy: any): string { return ` ## Cache Strategy Configuration ${cacheStrategy.metadata ? ` ### Metadata Cache - **TTL**: ${cacheStrategy.metadata.ttl} hours - **Max Size**: ${cacheStrategy.metadata.maxSize}MB \`\`\`kotlin @Singleton class MetadataCache @Inject constructor( @ApplicationContext private val context: Context ) { private val cache = LruCache<String, Any>(${cacheStrategy.metadata.maxSize} * 1024 * 1024) // ${cacheStrategy.metadata.maxSize}MB fun put(key: String, value: Any) { val expiryTime = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(${cacheStrategy.metadata.ttl}) cache.put(key, CacheItem(value, expiryTime)) } fun get(key: String): Any? { val item = cache.get(key) as? CacheItem ?: return null return if (item.isExpired()) { cache.remove(key) null } else { item.value } } } data class CacheItem(val value: Any, val expiryTime: Long) { fun isExpired(): Boolean = System.currentTimeMillis() > expiryTime } \`\`\`` : ''} ${cacheStrategy.images ? ` ### Image Cache - **Compression**: ${cacheStrategy.images.compression ? 'Enabled' : 'Disabled'} - **Max Resolution**: ${cacheStrategy.images.maxResolution} \`\`\`kotlin @Singleton class ImageCache @Inject constructor( @ApplicationContext private val context: Context ) { private val diskCache by lazy { DiskLruCache.open( File(context.cacheDir, "images"), 1, 1, 50 * 1024 * 1024 // 50MB ) } suspend fun cacheImage(url: String, bitmap: Bitmap) = withContext(Dispatchers.IO) { val key = hashKeyForDisk(url) diskCache.edit(key)?.let { editor -> val outputStream = editor.newOutputStream(0) ${cacheStrategy.images.compression ? ` bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream) ` : ` bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream) `} outputStream.close() editor.commit() } } } \`\`\`` : ''} `; } function generatePurgePolicy(purgePolicy: any): string { return ` ## Data Purge Policy **Retention Period**: ${purgePolicy.retentionDays} days **Triggers**: ${purgePolicy.conditions.join(', ')} \`\`\`kotlin @Singleton class DataPurgeManager @Inject constructor( private val database: DHIS2Database, @ApplicationContext private val context: Context ) { suspend fun purgeOldData() { val threshold = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(${purgePolicy.retentionDays}) database.withTransaction { database.dataElementDao().deleteOldRecords(threshold) database.eventDao().deleteOldRecords(threshold) database.organisationUnitDao().deleteOldRecords(threshold) } } fun checkPurgeConditions() { ${purgePolicy.conditions.includes('storage_full') ? ` val storageInfo = getStorageInfo() if (storageInfo.availableBytes < 100 * 1024 * 1024) { // 100MB lifecycleScope.launch { purgeOldData() } }` : ''} ${purgePolicy.conditions.includes('data_old') ? ` val lastPurge = getLastPurgeTime() if (System.currentTimeMillis() - lastPurge > TimeUnit.DAYS.toMillis(7)) { lifecycleScope.launch { purgeOldData() } }` : ''} } private fun getStorageInfo(): StorageInfo { val stat = StatFs(context.filesDir.path) return StorageInfo( totalBytes = stat.blockCountLong * stat.blockSizeLong, availableBytes = stat.availableBlocksLong * stat.blockSizeLong ) } } data class StorageInfo(val totalBytes: Long, val availableBytes: Long) \`\`\` `; }
- src/index.ts:51-60 (registration)Import of the generateStorageConfiguration helper function used by the tool handler.generateStorageConfiguration, generateCameraConfiguration, generateAndroidAuthenticationConfig, generateDataModelsConfiguration, generateAndroidTestingConfiguration, generateAndroidUIConfiguration, generateOfflineAnalyticsConfiguration, generateNotificationsConfiguration, generatePerformanceOptimizationConfiguration } from './android-generators.js';