From a5d012494cc950f83c2143e862e7e3bd7ad8d994 Mon Sep 17 00:00:00 2001 From: frankpreel Date: Wed, 26 Nov 2025 10:46:11 +0100 Subject: [PATCH 1/3] feat: Implement pagination for age rating provider. The 'getAgeRatings' method supports 'LIMIT' and 'OFFSET' URI query parameters, allowing clients to fetch blocked applications in chunks as limit was identified around 100 items in the list. --- .../e/apps/provider/AgeRatingProvider.kt | 31 +++++++++++++++---- .../apps/contract/ParentalControlContract.kt | 6 +++- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt b/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt index 1cd4991b5..2296b7dec 100644 --- a/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt +++ b/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 MURENA SAS + * Copyright (C) 2025 MURENA SAS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ import android.content.UriMatcher import android.database.Cursor import android.database.MatrixCursor import android.net.Uri +import android.os.Bundle import androidx.core.app.NotificationCompat import dagger.hilt.EntryPoint import dagger.hilt.InstallIn @@ -34,8 +35,11 @@ import dagger.hilt.components.SingletonComponent import foundation.e.apps.R import foundation.e.apps.contract.ParentalControlContract.COLUMN_LOGIN_TYPE import foundation.e.apps.contract.ParentalControlContract.COLUMN_PACKAGE_NAME +import foundation.e.apps.contract.ParentalControlContract.LIMIT +import foundation.e.apps.contract.ParentalControlContract.OFFSET import foundation.e.apps.contract.ParentalControlContract.PATH_BLOCKLIST import foundation.e.apps.contract.ParentalControlContract.PATH_LOGIN_TYPE +import foundation.e.apps.contract.ParentalControlContract.TOTAL_PACKAGE_NAMES import foundation.e.apps.data.ResultSupreme import foundation.e.apps.data.blockedApps.BlockedAppRepository import foundation.e.apps.data.enums.Source @@ -78,6 +82,8 @@ class AgeRatingProvider : ContentProvider() { private const val CHANNEL_ID = "applounge_provider" private const val NOTIFICATION_ID = 77 private const val AUTHORITY = "foundation.e.apps.provider" + private const val DEFAULT_LIMIT_VALUE = 50 + private const val DEFAULT_OFFSET_VALUE = 0 } private lateinit var authenticatorRepository: AuthenticatorRepository @@ -113,7 +119,7 @@ class AgeRatingProvider : ContentProvider() { val code = uriMatcher.match(uri) return when (code) { UriCode.LoginType.code -> getLoginType() - UriCode.AgeRating.code -> getAgeRatings() + UriCode.AgeRating.code -> getAgeRatings(uri) else -> null } } @@ -124,20 +130,33 @@ class AgeRatingProvider : ContentProvider() { return cursor } - private fun getAgeRatings(): Cursor { + private fun getAgeRatings(uri: Uri?): Cursor { val cursor = MatrixCursor(arrayOf(COLUMN_PACKAGE_NAME)) + val limit = (uri?.getQueryParameter(LIMIT)?.toIntOrNull() ?: DEFAULT_LIMIT_VALUE).coerceAtLeast(0) + val offset = (uri?.getQueryParameter(OFFSET)?.toIntOrNull() ?: DEFAULT_OFFSET_VALUE).coerceAtLeast(0) runBlocking { showNotification() val packageNames = appLoungePackageManager.getAllUserApps().map { it.packageName } - Timber.d("Start preparing blocklist from ${packageNames.size} apps.") + val totalPackageNames = packageNames.size + + cursor.extras = Bundle().apply { + putInt(TOTAL_PACKAGE_NAMES, totalPackageNames) + putInt(LIMIT, limit) + putInt(OFFSET, offset) + } + val pagedPackageNames = packageNames + .drop(offset) + .take(limit) + + Timber.d("Start preparing blocklist from ${pagedPackageNames.size} apps.") withContext(IO) { try { - if (packageNames.isEmpty()) return@withContext cursor + if (pagedPackageNames.isEmpty()) return@withContext cursor initAuthData() ensureAgeGroupDataExists() - compileAppBlockList(cursor, packageNames) + compileAppBlockList(cursor, pagedPackageNames) } catch (e: Exception) { Timber.e("AgeRatingProvider", "Error fetching age ratings", e) } diff --git a/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt b/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt index 0b6797e56..60c149e5f 100644 --- a/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt +++ b/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt @@ -1,5 +1,5 @@ /* - * Copyright MURENA SAS 2024 + * Copyright MURENA SAS 2025 * Apps Quickly and easily install Android apps onto your device! * * This program is free software: you can redistribute it and/or modify @@ -21,6 +21,10 @@ package foundation.e.apps.contract object ParentalControlContract { const val COLUMN_PACKAGE_NAME = "package_name" + const val TOTAL_PACKAGE_NAMES = "total_package_names" + const val OFFSET = "offset" + const val LIMIT = "limit" + const val COLUMN_LOGIN_TYPE = "login_type" const val PATH_LOGIN_TYPE = "login_type" -- GitLab From 40b9288dc2f1a9a82af3a258208a2ea4bbd296df Mon Sep 17 00:00:00 2001 From: frankpreel Date: Wed, 26 Nov 2025 11:17:15 +0100 Subject: [PATCH 2/3] feat: ParentalControlData version 1.2.0 --- .../foundation/e/apps/provider/AgeRatingProvider.kt | 4 ++-- parental-control-data/README.md | 11 ++++++++++- parental-control-data/build.gradle | 2 +- .../e/apps/contract/ParentalControlContract.kt | 2 ++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt b/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt index 2296b7dec..e0179250b 100644 --- a/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt +++ b/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt @@ -35,6 +35,8 @@ import dagger.hilt.components.SingletonComponent import foundation.e.apps.R import foundation.e.apps.contract.ParentalControlContract.COLUMN_LOGIN_TYPE import foundation.e.apps.contract.ParentalControlContract.COLUMN_PACKAGE_NAME +import foundation.e.apps.contract.ParentalControlContract.DEFAULT_LIMIT_VALUE +import foundation.e.apps.contract.ParentalControlContract.DEFAULT_OFFSET_VALUE import foundation.e.apps.contract.ParentalControlContract.LIMIT import foundation.e.apps.contract.ParentalControlContract.OFFSET import foundation.e.apps.contract.ParentalControlContract.PATH_BLOCKLIST @@ -82,8 +84,6 @@ class AgeRatingProvider : ContentProvider() { private const val CHANNEL_ID = "applounge_provider" private const val NOTIFICATION_ID = 77 private const val AUTHORITY = "foundation.e.apps.provider" - private const val DEFAULT_LIMIT_VALUE = 50 - private const val DEFAULT_OFFSET_VALUE = 0 } private lateinit var authenticatorRepository: AuthenticatorRepository diff --git a/parental-control-data/README.md b/parental-control-data/README.md index 5a08135e7..999e80e6d 100644 --- a/parental-control-data/README.md +++ b/parental-control-data/README.md @@ -15,4 +15,13 @@ Initial version : ParentalControlContract TypeAppManagement: - CONTENT_RATING Legacy mode validation based on age - SECURITY_CODE Security code request by the Parental Controls application -- DISABLED_MODE No restriction \ No newline at end of file +- DISABLED_MODE No restriction + +## 1.2.0 + +ParentalControlContract: +- TOTAL_PACKAGE_NAMES Total number of items to be processed +- OFFSET +- LIMIT +- DEFAULT_LIMIT_VALUE 50 +- DEFAULT_OFFSET_VALUE 0 \ No newline at end of file diff --git a/parental-control-data/build.gradle b/parental-control-data/build.gradle index a4c865106..75f7c659c 100644 --- a/parental-control-data/build.gradle +++ b/parental-control-data/build.gradle @@ -14,7 +14,7 @@ publishing { jar(MavenPublication) { groupId = 'foundation.e.apps' artifactId = 'ParentalControlData' - version = '1.1.0' + version = '1.2.0' artifact("$buildDir/libs/${project.name}.jar") diff --git a/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt b/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt index 60c149e5f..95d1c4646 100644 --- a/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt +++ b/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt @@ -24,6 +24,8 @@ object ParentalControlContract { const val TOTAL_PACKAGE_NAMES = "total_package_names" const val OFFSET = "offset" const val LIMIT = "limit" + const val DEFAULT_LIMIT_VALUE = 50 + const val DEFAULT_OFFSET_VALUE = 0 const val COLUMN_LOGIN_TYPE = "login_type" -- GitLab From f190029b5bebb276183c8458598964416e17c69e Mon Sep 17 00:00:00 2001 From: frankpreel Date: Wed, 26 Nov 2025 16:55:42 +0100 Subject: [PATCH 3/3] feat: replace totalPackageNames by totalPackageNumber --- .../java/foundation/e/apps/provider/AgeRatingProvider.kt | 6 +++--- parental-control-data/README.md | 2 +- .../foundation/e/apps/contract/ParentalControlContract.kt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt b/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt index e0179250b..efd1c7ed7 100644 --- a/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt +++ b/app/src/main/java/foundation/e/apps/provider/AgeRatingProvider.kt @@ -41,7 +41,7 @@ import foundation.e.apps.contract.ParentalControlContract.LIMIT import foundation.e.apps.contract.ParentalControlContract.OFFSET import foundation.e.apps.contract.ParentalControlContract.PATH_BLOCKLIST import foundation.e.apps.contract.ParentalControlContract.PATH_LOGIN_TYPE -import foundation.e.apps.contract.ParentalControlContract.TOTAL_PACKAGE_NAMES +import foundation.e.apps.contract.ParentalControlContract.TOTAL_PACKAGE_NUMBER import foundation.e.apps.data.ResultSupreme import foundation.e.apps.data.blockedApps.BlockedAppRepository import foundation.e.apps.data.enums.Source @@ -138,10 +138,10 @@ class AgeRatingProvider : ContentProvider() { runBlocking { showNotification() val packageNames = appLoungePackageManager.getAllUserApps().map { it.packageName } - val totalPackageNames = packageNames.size + val totalPackageNumber = packageNames.size cursor.extras = Bundle().apply { - putInt(TOTAL_PACKAGE_NAMES, totalPackageNames) + putInt(TOTAL_PACKAGE_NUMBER, totalPackageNumber) putInt(LIMIT, limit) putInt(OFFSET, offset) } diff --git a/parental-control-data/README.md b/parental-control-data/README.md index 999e80e6d..46aefed92 100644 --- a/parental-control-data/README.md +++ b/parental-control-data/README.md @@ -20,7 +20,7 @@ TypeAppManagement: ## 1.2.0 ParentalControlContract: -- TOTAL_PACKAGE_NAMES Total number of items to be processed +- TOTAL_PACKAGE_NUMBER Total number of items to be processed - OFFSET - LIMIT - DEFAULT_LIMIT_VALUE 50 diff --git a/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt b/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt index 95d1c4646..793a1473c 100644 --- a/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt +++ b/parental-control-data/src/main/java/foundation/e/apps/contract/ParentalControlContract.kt @@ -21,7 +21,7 @@ package foundation.e.apps.contract object ParentalControlContract { const val COLUMN_PACKAGE_NAME = "package_name" - const val TOTAL_PACKAGE_NAMES = "total_package_names" + const val TOTAL_PACKAGE_NUMBER = "total_package_number" const val OFFSET = "offset" const val LIMIT = "limit" const val DEFAULT_LIMIT_VALUE = 50 -- GitLab