Skip to content

Comments

refactor(service): Optimize notification updates and bump dependencies#31

Merged
Steve-Mr merged 5 commits intomainfrom
dev
Sep 21, 2025
Merged

refactor(service): Optimize notification updates and bump dependencies#31
Steve-Mr merged 5 commits intomainfrom
dev

Conversation

@Steve-Mr
Copy link
Owner

Summary

This pull request introduces significant performance optimizations to the foreground service, refactors the broadcast receiver logic for better reliability, and updates all major project dependencies to their latest versions. The primary goals are to improve the app's responsiveness, streamline the codebase, and ensure compatibility with the latest libraries.

Changes

  • Dependency Upgrades:

    • Upgraded Android Gradle Plugin to 8.11.2, Kotlin to 2.2.20, and KSP to 2.2.20-2.0.3.
    • Updated various AndroidX libraries, including activity, lifecycle, compose, room, and work.
    • Updated app versionName to 2025.09.21.
  • Performance Optimizations:

    • Implemented pre-caching for volume notification icons into a SparseIntArray upon service creation. This avoids repeated, expensive calls to resources.getIdentifier() every time the notification is updated, significantly improving performance.
    • Replaced the debounce mechanism in VolumeReceiver with a more efficient throttle mechanism (THROTTLE_TIME_MS). This ensures more responsive and predictable notification updates when the volume changes, without using a Handler to post delayed messages.
  • Refactoring:

    • Removed the standalone SleepReceiver to simplify the architecture.
    • Consolidated the notification update logic for the sleep timer directly into ForegroundService by handling the BROADCAST_ACTION_SLEEPTIMER_UPDATE action in onStartCommand.
    • Modified MuteMediaReceiver to use startService() instead of sendBroadcast() to communicate with the ForegroundService. This is a more direct and reliable way to trigger updates.

This commit refactors the SleepTimer update mechanism. Instead of using a BroadcastReceiver (`SleepReceiver`) to handle `BROADCAST_ACTION_SLEEPTIMER_UPDATE`, this action is now directly sent to and handled by `ForegroundService`.

Key changes:
- In `MuteMediaReceiver`, intents with `BROADCAST_ACTION_SLEEPTIMER_UPDATE` are now directed to `ForegroundService` using `startService()`.
- `ForegroundService` now handles `BROADCAST_ACTION_SLEEPTIMER_UPDATE` in its `onStartCommand` method, triggering `updateForegroundNotification()`.
- The `sleepReceiver` instance and its registration/unregistration in `ForegroundService` have been removed/commented out as it's no longer needed for this specific update.
The `VolumeReceiver` previously used a debounce mechanism to handle volume changes. This has been replaced with a throttle mechanism.

The constant `DEBOUNCE_TIME_MS` has been renamed to `THROTTLE_TIME_MS` and its value changed from `500` to `100L`.

The `VolumeReceiver`'s `onReceive` method now checks if the time since the last update is greater than or equal to `THROTTLE_TIME_MS`. If it is, `updateNotification` is called immediately. Otherwise, the event is ignored. The `Handler` and delayed `postDelayed` call have been removed.
This commit introduces a preloading mechanism for volume icons used in notifications.

Instead of dynamically looking up the resource ID for each volume percentage (0-100) every time a notification is generated, this change:
- Creates a `SparseIntArray` called `volumeIconMap`.
- Populates `volumeIconMap` during the `onCreate` lifecycle method of the `ForegroundService`. It iterates from 0 to 100, finds the drawable resource ID for each `num_X` (where X is the percentage), and stores it in the map.
- Modifies `generateNotificationIcon` to directly retrieve the resource ID from `volumeIconMap` using the current volume percentage.

This optimization aims to improve performance by reducing repeated resource lookups, especially when volume changes frequently and notifications need to be updated. A default value of 0 is used if a specific icon is not found in the map.
The `SleepReceiver` class and its associated broadcast registration and handling logic within `ForegroundService` have been removed. The functionality for updating notifications based on sleep timer events is no longer handled through this broadcast mechanism.
This commit updates various dependencies to their latest versions and modifies the `versionName`.
@gemini-code-assist
Copy link

Summary of Changes

Hello @Steve-Mr, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on enhancing the application's performance and maintainability by optimizing core service operations and updating its foundational libraries. It streamlines notification updates, particularly for volume changes, by introducing pre-caching and a more efficient throttling mechanism. Additionally, the architecture around sleep timer notifications has been simplified, and all major project dependencies have been brought up to date to ensure the application remains robust and compatible with the latest Android ecosystem.

Highlights

  • Dependency Updates: All major project dependencies, including Android Gradle Plugin, Kotlin, KSP, AndroidX libraries (activity, lifecycle, compose, room, work), and Compose BOM, have been updated to their latest versions, ensuring compatibility and leveraging new features.
  • Performance Optimization (Volume Icons): Volume notification icons are now pre-cached into a SparseIntArray upon service creation, eliminating expensive runtime calls to resources.getIdentifier() and significantly improving notification update performance.
  • Performance Optimization (Volume Receiver): The VolumeReceiver now uses a more efficient throttle mechanism (THROTTLE_TIME_MS set to 100ms) instead of a debounce with a Handler, leading to more responsive and predictable notification updates for volume changes.
  • Sleep Timer Refactoring: The SleepReceiver has been removed, and its notification update logic is now directly handled within the ForegroundService via onStartCommand for the BROADCAST_ACTION_SLEEPTIMER_UPDATE action, simplifying the architecture.
  • Inter-component Communication: MuteMediaReceiver now uses startService() instead of sendBroadcast() to communicate with the ForegroundService for sleep timer updates, providing a more direct and reliable communication channel.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces some excellent performance optimizations and refactoring, and the dependency updates are comprehensive. My review focuses on the code changes, where I've identified a couple of areas for improvement regarding code duplication and redundant logic. Specifically, I've suggested a refactoring in MuteMediaReceiver to avoid duplicating code for starting a service and pointed out a redundant method call in ForegroundService that leads to unnecessary work. Overall, the changes are solid and effectively improve the app's performance and maintainability as described.

Comment on lines 29 to 46
if (p1?.action == BROADCAST_ACTION_SLEEPTIMER_CANCEL ||
p1?.action == BROADCAST_ACTION_SLEEPTIMER_INCREMENT ||
p1?.action == BROADCAST_ACTION_SLEEPTIMER_DECREMENT) {

p0?.handle(p1)
val intent = Intent(BROADCAST_ACTION_SLEEPTIMER_UPDATE)
p0?.sendBroadcast(intent)

val intent = Intent(p0, ForegroundService::class.java)
intent.action = BROADCAST_ACTION_SLEEPTIMER_UPDATE
p0?.startService(intent)
}

if (p1?.action == BROADCAST_ACTION_SLEEPTIMER_TOGGLE) {
p0?.toggle()
val intent = Intent(BROADCAST_ACTION_SLEEPTIMER_UPDATE)
p0?.sendBroadcast(intent)

val intent = Intent(p0, ForegroundService::class.java)
intent.action = BROADCAST_ACTION_SLEEPTIMER_UPDATE
p0?.startService(intent)
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for handling sleep timer actions involves creating an Intent and calling startService in two separate if blocks, which leads to code duplication. You can refactor this using a when statement to handle the different actions and then call startService once. This will make the code more concise and easier to maintain.

        val action = p1?.action
        val sleepTimerActionHandled = when (action) {
            BROADCAST_ACTION_SLEEPTIMER_CANCEL,
            BROADCAST_ACTION_SLEEPTIMER_INCREMENT,
            BROADCAST_ACTION_SLEEPTIMER_DECREMENT -> {
                p0?.handle(p1)
                true
            }
            BROADCAST_ACTION_SLEEPTIMER_TOGGLE -> {
                p0?.toggle()
                true
            }
            else -> false
        }

        if (sleepTimerActionHandled) {
            val intent = Intent(p0, ForegroundService::class.java).apply {
                this.action = BROADCAST_ACTION_SLEEPTIMER_UPDATE
            }
            p0?.startService(intent)
        }

Comment on lines +179 to +182
BROADCAST_ACTION_SLEEPTIMER_UPDATE -> {
Log.d(TAG, "Sleep timer update action received via onStartCommand.")
updateForegroundNotification()
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The call to updateForegroundNotification() on line 181 is redundant because the same function is called unconditionally on line 186. This causes the notification to be updated twice for the BROADCAST_ACTION_SLEEPTIMER_UPDATE action, which is inefficient. You can safely remove the call from this block, as the one on line 186 will handle the update.

            BROADCAST_ACTION_SLEEPTIMER_UPDATE -> {
                Log.d(TAG, "Sleep timer update action received via onStartCommand.")
            }

@Steve-Mr Steve-Mr merged commit 8123868 into main Sep 21, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant