DESCO Smart is a powerful and lightweight Android application designed to help DESCO prepaid electricity users monitor their consumption with ease. It provides real-time balance updates, detailed recharge history, and smart low-balance notifications to ensure you never run out of electricity unexpectedly.
Developed by Utsho with a focus on simplicity and utility.
Important
Disclaimer: This repository is an independent application project and is not an official DESCO application. It depends on public DESCO web API endpoints, which may change without notice.
You can download the latest version of the app directly from the link below:
Caution
Important for Notifications: To get low-balance alerts correctly, you must set the App Battery to "Unrestricted", "Don't Optimize" or "No Restrictions" and enable "Auto-start" in your phone settings. Otherwise, Android may stop the background check.
Note: After downloading, you may need to allow "Install from Unknown Sources" in your Android settings to install the APK.
- Connect a prepaid meter using either an account number or meter number.
- Save and manage multiple meters locally.
- Switch the active meter from the main screen.
- View customer information such as name, account number, meter number, phone, address, feeder, and phase.
- View the current prepaid balance and current-month spending.
- Estimate the full-month cost from the amount used so far.
- Show a suggested recharge amount when the projected monthly cost exceeds the remaining balance.
- Display a 12-month usage chart and toggle between kWh and BDT.
- View approximately one year of recharge history, including amount, date, payment mode, transaction/order ID, and energy amount.
- Calculate recharge totals for the current month and current year when the full history response is available.
- Configure a separate low-balance threshold for each saved meter.
- Run background balance checks and send a notification when a meter newly enters the low-balance state.
- Resume background scheduling after device reboot or app replacement.
- Generate a multi-page PDF recharge report and save it under
Downloads/DescoReports.
SplashActivity
|
+-- no saved/active meter --> LoginActivity --> verify meter --> MainActivity
|
+-- active meter exists -------------------------------> MainActivity
MainActivity
|
+-- DashboardFragment -> customer, balance, estimate, 12-month chart
+-- HistoryFragment -> recharge history and totals
+-- ReportsFragment -> PDF report generation
+-- SettingsFragment -> rename/delete meters, alert limits, scheduling
|
+-- Switch Meter dialog / AddMeterActivity
| Area | Technology |
|---|---|
| Language | Java 11 |
| UI | Android Views, Material Components, View Binding |
| Local database | Room 2.6.1 |
| Networking | Retrofit 2.9.0 + OkHttp 4.12.0 + Gson |
| Background work | WorkManager 2.9.0 |
| Charts | MPAndroidChart 3.1.0 |
Android PdfDocument |
|
| Minimum Android | API 24 |
| Target / Compile SDK | API 35 |
| Build system | Gradle 8.13 / Android Gradle Plugin 8.12.3 |
app/src/main/
├── AndroidManifest.xml
├── java/com/example/descosmartapp/
│ ├── api/
│ │ ├── ApiClient.java # Retrofit/OkHttp creation and caching
│ │ └── DescoApi.java # DESCO Retrofit endpoint definitions
│ ├── db/
│ │ ├── AppDatabase.java # Room database singleton
│ │ ├── DbExecutor.java # Single-thread DB execution helper
│ │ ├── MeterDao.java # Meter persistence operations
│ │ └── MeterProfile.java # Room entity
│ ├── model/
│ │ ├── BalanceResponse.java
│ │ ├── CustomerResponse.java
│ │ ├── MonthlyResponse.java
│ │ └── RechargeResponse.java
│ ├── service/
│ │ ├── DescoService.java # API facade, fallback logic, alerts
│ │ └── MeterRegistration.java # Meter lookup and save workflow
│ ├── ui/
│ │ ├── SplashActivity.java
│ │ ├── LoginActivity.java
│ │ ├── MainActivity.java
│ │ ├── AddMeterActivity.java
│ │ ├── adapters/
│ │ │ ├── MeterManageAdapter.java
│ │ │ └── RechargeAdapter.java
│ │ └── fragments/
│ │ ├── DashboardFragment.java
│ │ ├── HistoryFragment.java
│ │ ├── ReportsFragment.java
│ │ └── SettingsFragment.java
│ ├── utils/
│ │ ├── Constants.java
│ │ ├── DateRanges.java
│ │ ├── ReportPdfGenerator.java
│ │ └── UiInsets.java
│ └── worker/
│ ├── BalanceCheckWorker.java
│ ├── BootReceiver.java
│ ├── ScheduleCalculator.java
│ └── WorkScheduler.java
└── res/
├── layout/ # Activities, fragments and list rows
├── drawable/ # App UI backgrounds and icons
├── menu/ # Bottom navigation menu
└── values/ # Colors, strings and themes
The project intentionally demonstrates several common software design patterns.
| Pattern | Main location | Implementation | Why it is used |
|---|---|---|---|
| Singleton | db/AppDatabase.java |
instance + getInstance() |
Keeps one Room database instance for the entire application. |
| Singleton | service/DescoService.java |
Holder + getInstance() |
Keeps one shared service object for DESCO API operations. |
| DAO | db/MeterDao.java |
MeterDao interface |
Separates Room/SQL operations from UI and service code. |
| Facade | service/DescoService.java |
Public fetch...() methods |
Hides Retrofit calls, primary/fallback APIs, validation, merging, and notification helpers behind a simpler interface. |
| Adapter | ui/adapters/RechargeAdapter.java |
RecyclerView adapter | Converts recharge model objects into RecyclerView rows. |
| Adapter | ui/adapters/MeterManageAdapter.java |
RecyclerView adapter | Converts saved meter models into interactive meter-management rows. |
| Strategy | service/DescoService.java |
DataCheck<T> + withFallback() |
Lets each API operation provide its own “valid response” rule while reusing the same fallback algorithm. |
| Builder | api/ApiClient.java |
Retrofit.Builder, OkHttpClient.Builder |
Builds configured networking objects step by step. |
| Builder | worker/WorkScheduler.java |
Constraints.Builder, OneTimeWorkRequest.Builder |
Builds configured WorkManager jobs step by step. |
| Template Method | ui/MainActivity.java |
overridden onCreate() |
Android owns the Activity lifecycle and calls the subclass hook. |
| Template Method | ui/adapters/RechargeAdapter.java |
overridden adapter methods | RecyclerView defines the rendering lifecycle and calls the adapter hooks. |
| Template Method | worker/BalanceCheckWorker.java |
overridden doWork() |
WorkManager controls execution and calls the task-specific work hook. |
- Singleton: One shared object is returned throughout the application.
- DAO: Database operations are isolated behind a dedicated interface.
- Facade: A simple service interface hides several complex subsystems.
- Adapter: Converts one data/interface form into the form required by another component.
- Strategy: Interchangeable validation rules are passed into one common algorithm.
- Builder: A complex object is configured step by step and created with
build(). - Template Method: A framework defines the overall algorithm/lifecycle and a subclass overrides selected hook methods.
Two base URLs are configured in utils/Constants.java:
Primary: https://prepaid.desco.org.bd/api/unified/customer/
Fallback: https://prepaid.desco.org.bd/api/tkdes/customer/
DescoService first tries the primary API. If the request fails or does not contain usable data, it executes the equivalent call against the fallback API.
| Operation | Endpoint | Main parameters |
|---|---|---|
| Customer by account | getCustomerInfo |
accountNo |
| Customer by meter | getCustomerInfo |
meterNo |
| Balance | getBalance |
accountNo |
| Monthly consumption | getCustomerMonthlyConsumption |
accountNo, monthFrom, monthTo |
| Recharge history | getRechargeHistory |
accountNo, dateFrom, dateTo |
| Recharge history by meter | getRechargeHistory |
meterNo, dateFrom, dateTo |
The model classes include Gson alternate field names where the upstream API may return different JSON property names.
The app requests roughly the previous 12 months in two date ranges and merges the results. Splitting the request helps work with the upstream recharge-history service while still presenting one combined list.
Room stores saved meter profiles in a database named:
desco_db
The meters table contains:
| Field | Purpose |
|---|---|
id |
Auto-generated primary key |
label |
User-friendly name such as Home or Office |
accountNo |
DESCO account number |
meterNo |
DESCO meter number |
lowBalanceThreshold |
Alert threshold in BDT |
isActive |
Whether this is the currently selected meter |
createdAt |
Local creation timestamp |
meterState |
Retained only for Room v1 schema compatibility |
MeterDao.activateMeter() deactivates all meters before selecting one, so the app normally keeps a single active meter.
WorkScheduler schedules a one-time WorkManager request for the next configured check and BalanceCheckWorker schedules the following check when its work completes.
Configured check times are:
07:00
10:00
13:00
17:00
21:00
The worker requires an active network connection. For each saved meter it:
- Fetches the latest balance.
- Compares the balance with that meter's configured threshold.
- Sends a high-priority notification when the meter newly becomes low.
- Stores a small
SharedPreferencesflag so the same low state is not repeatedly notified. - Clears that flag after the balance rises above the threshold, allowing a future low-balance transition to notify again.
BootReceiver restores scheduling after boot, package replacement, or supported quick-boot broadcasts when saved meters exist.
WorkManager execution is OS-managed, so these times should be treated as desired check points rather than alarm-clock-level exact execution times.
If you are not receiving background low-balance notifications, please check the following settings on your Android device (especially for Xiaomi, Samsung, Oppo, and Vivo):
- Battery Optimization: Go to App Info > Battery and set it to "Unrestricted" or "Don't Optimize".
- Auto-start: If your phone has an "Auto-start" setting, make sure it is enabled for DESCO Smart.
- Notification Permissions: Ensure that notifications are allowed in App Info > Notifications.
These settings prevent the Android system from killing the app's background processes, ensuring you get alerts on time.
The estimated full-month cost is a simple linear projection:
estimated month cost = (cost used so far / elapsed days) × days in current month
If the projected remaining requirement is greater than the current balance, the suggested recharge is rounded upward to the next BDT 100.
This is an estimate only; it does not model tariff slabs, future behavior changes, emergency balance rules, or other billing adjustments.
The Reports screen creates a landscape recharge-history PDF containing:
- DESCO-style heading and report title
- Account and meter information
- User-defined meter name
- Current balance and configured alert limit
- Customer name, address, and S&D information when available
- Report period
- Recharge rows with order number, meter number, date, total amount, and energy amount
- Generated date and page numbering
- Android 10+ (API 29+): saved with MediaStore under
Downloads/DescoReports. - Android 9 and lower: saved directly to the public Downloads directory and requires legacy write-storage permission.
Example filename:
DESCO_Home_Recharge_Report_20260809_011500.pdf
The manifest requests:
| Permission | Reason |
|---|---|
INTERNET |
DESCO API requests |
POST_NOTIFICATIONS |
Low-balance notifications on Android 13+ |
RECEIVE_BOOT_COMPLETED |
Restore background balance scheduling after reboot |
WRITE_EXTERNAL_STORAGE (max API 28) |
Save reports on legacy Android versions |
The application disables cleartext HTTP traffic and does not enable Android backup.
- Android Studio with support for Android Gradle Plugin 8.12.x
- JDK 17 for the Android Gradle Plugin/Gradle build runtime (the app source/target compatibility is Java 11)
- Android SDK Platform 35
- An Android device/emulator running API 24 or newer
- Internet access for Gradle dependencies and live DESCO data
- Clone or download the repository.
- Open the
DescoSmartAppproject folder in Android Studio. - Allow Gradle to sync and download dependencies.
- Make sure Android SDK 36 is installed.
- Run the
appconfiguration on an emulator or physical device.
macOS/Linux:
./gradlew assembleDebugWindows:
gradlew.bat assembleDebugThe debug APK is normally created under:
app/build/outputs/apk/debug/
- Launch the app.
- Enter a DESCO account number or meter number.
- Optionally give the meter a friendly name.
- Tap Verify & Add Meter.
- Use the bottom navigation for Dashboard, History, Reports, and Settings.
- Add extra meters from the switch-meter dialog or Settings.
- Set the desired low-balance limit for each meter in Settings.
- Grant notification permission on Android 13+ if you want background alerts.
ApiClient contains a TLS compatibility configuration that currently allows all certificates and hostnames. This is intentionally used to ensure reliable data fetching from DESCO utility servers, which may use certificates not recognized by default Android system trust managers.
This behavior is necessary for consistent operation with existing DESCO endpoints but it disables standard certificate validation. This should be reviewed if the app is intended for production-grade security handling sensitive user credentials. Prefer fixing server-side certificate chains or using specific certificate pinning where possible.
- Saved meter profiles and alert thresholds are stored locally in Room.
- Low-balance notification state is stored locally in
SharedPreferences. - Meter/account identifiers are sent to the configured DESCO API endpoints when data is requested.
- Generated reports are written to the device Downloads area.
- The project does not contain an account-password login flow or its own remote user database.
The repository currently includes only the default sample tests:
- Local JUnit test checking
2 + 2 = 4. - Instrumented test checking the application package name.
For stronger coverage, useful next tests would include:
ScheduleCalculator.nextDelay()around exact check times and midnight.DateRangesmonth/year boundaries.DescoService.stateLabel()andshowAlert()threshold behavior.MeterDaoactive-meter transaction rules.- Response parsing for alternate DESCO JSON field names.
- Monthly estimate and recharge-total calculations.
- Live features depend on the availability and response format of external DESCO endpoints.
- There is no offline cache for live customer, balance, consumption, or recharge responses.
- The monthly bill estimate uses linear projection rather than a full electricity tariff calculation.
- Background work can be delayed by Android battery optimization, Doze, OEM policies, or lack of connectivity.
- Recharge history totals are intentionally hidden when only a partial yearly history request succeeds.
- The current test suite is minimal.
- The project has no license file, so reuse/distribution terms are not explicitly granted by this repository.
| Class | Responsibility |
|---|---|
ApiClient |
Builds and caches Retrofit clients and shared OkHttp configuration. |
DescoApi |
Declares HTTP endpoints. |
DescoService |
Central API facade, fallback handling, UI mapping, balance state helpers, notifications. |
MeterRegistration |
Looks up input as account/meter number and persists the verified meter. |
AppDatabase / MeterDao |
Stores and manages local meter profiles. |
DashboardFragment |
Shows live meter/customer data, estimates, and monthly chart. |
HistoryFragment |
Displays recharge records and totals. |
ReportsFragment |
Coordinates data collection and PDF generation. |
ReportPdfGenerator |
Draws and saves the multi-page recharge report. |
MeterManageAdapter |
Renames, deletes, and updates thresholds for saved meters. |
WorkScheduler |
Schedules the next background balance check. |
BalanceCheckWorker |
Fetches balances and triggers low-balance notifications. |
BootReceiver |
Restores background scheduling after reboot/update. |
App name: DESCO Smart
Application ID: com.example.descosmartapp
Version: 1.0 (versionCode 1)