GSOC 2025: Onboarding Revamp in ListenBrainz Android

GSOC 2025: Onboarding Revamp in ListenBrainz Android

Introduction

Contact Information

Name: Hemang Mishra

IRC nick: hemang-mishra

Email: hemangmishra25@gmail.com

GitHub: Hemang Mishra

LinkedIn: Hemang Mishra | LinkedIn

I am a sophomore at the Indian Institute of Information Technology Jabalpur (IIITDMJ), pursuing B.Tech in Computer Science and Engineering. I love listening to music (especially during long coding hours). I started exploring Android development in my first semester and built some apps for myself (which I still use daily). Along with Android, I am into Competitive Programming and solving challenging problems. But what excites me the most is using my skills to solve real-life problems.

I am highly familiar with the entire tech stack, having worked extensively with Kotlin, Jetpack Compose, and MVVM across multiple projects. More importantly, I am genuinely passionate about this project because it directly impacts user experience and privacy—two aspects I deeply care about. ListenBrainz, with its community-driven nature, has the potential to grow into a social, interactive platform for music lovers. Contributing to this evolution and enhancing how users engage with their listening data makes this opportunity incredibly exciting for me.

Project Overview

ListenBrainz Android is an amazing app that lets users track their music listening habits while staying open-source and privacy-focused. But right now, the onboarding flow has some bugs and is missing key features, which affects user retention and doesn’t explain why certain permissions are needed. A well-designed onboarding experience is crucial, and I want to make sure ListenBrainz gets it right.

One of the biggest problems we need to fix is how Listen Submission works out of the box. Right now, listens can be collected from unintended apps (like YouTube) without properly informing users, which is a privacy concern and might make people lose trust in the app. To solve this, I’ll introduce a dedicated Listen Submission screen during onboarding so users have full control right from the start.

Another key improvement is keeping the app updated seamlessly, so users always get the latest features and bug fixes without any hassle.

My Contributions

I have been a contributor to ListenBrainz since December 2024 and have worked on implementing the Created For You screen and the Playlist screen on Android, along with fixing some major bugs.

Deliverables

  1. Revamp the Onboarding Flow by removing the limurse library and implementing a scalable onboarding experience.
  2. Add an additional onboarding screen to inform users about the option to submit logs from settings in case they encounter any issues.
  3. Show proper permission rationales for all requested permissions.
  4. Handle cases where users deny permissions twice, ensuring fallback options and re-directing to device settings where necessary.
  5. Add a Listen Submission Screen, allowing users to choose which apps ListenBrainz should collect listens from. Users will also have an option to submit listens automatically when a new player is detected.
  6. Redesign the Sign-in Screen (keeping the functionality intact) but improving its UX by adding a link to create a new account and enhancing navigation.
  7. Include a “Report Bug” button on the Sign-in Screen, allowing users to submit bug reports. This button will open a dialog for easy bug reporting.
  8. Introduce Update Prompts, ensuring users are informed about new updates from the Play Store or GitHub (for F-Droid users).
  9. Add necessary options like disabling Battery Optimization and checking for updates in App Settings.

Understanding the New Onboarding Flow

Onboarding is the first interaction a user has with ListenBrainz, and it plays a huge role in user retention. So I have created a prototype of the proposed onboarding flow.

User Flow Prototype : Check out

Now, I will breakdown the entire experience for a new user at ListenBrainz.

1. Onboarding Screens

The new onboarding flow will introduce users to four key functionalities of ListenBrainz:

  1. Listen Together – ListenBrainz isn’t just a music tracker; it’s a community. Users can follow, share, recommend, and collaborate with friends.
  2. Reviews – Users can like, dislike, add, and edit reviews, making ListenBrainz a space for genuine music discussions.
  3. BrainzPlayer – Users can play local songs directly within ListenBrainz, eliminating the need for an external player.
  4. Submit Logs – If users face any issues while using ListenBrainz, they can submit logs to help troubleshoot problems. This can be done via Settings > Report A Bug.

2. Sign-In Screen

A better-integrated login experience will improve the transition into the app.

  • Users will be redirected to the website to log in.
  • A “Create Account” option will be added, linking to the website’s signup page.
  • If login fails due to any error, it will be gracefully handled, ensuring users aren’t stuck in an infinite loop.
  • After successful login, users will be redirected to Permissions Screen.
  • A “Report Bug” button will be added to the sign-in screen, allowing users to report any issues they face during the sign-in or onboarding process. This button will open a dialog where users can submit bug reports easily. (Attached is the image of the dialog and button for reference.)

This will make the sign-in process more user-friendly and prevent abrupt interruptions.

3. Permissions Screen

To ensure transparency, the Permissions screen will display clear rationale for each requested permission.

  • Initially a rationale box will explain why the permission is required.
  • If a permission is declined twice, the rationale will change, informing that they have permanently declined the permission and will have to be redirected to device settings to enable those settings.

Image

  • For notification read access and battery optimization, users will be redirected to device settings to enable them manually.
  • Users will have the option to proceed without granting permissions, but a dialog will explain the consequences. (See image below)

Image

4. Listening Apps Screen

This is a crucial addition that will give users more control over their listening data.

  • Users can select the apps from which they want listens to be submitted.
  • This prevents unwanted listens from being recorded.
  • If a new music app is detected, users will be prompted to decide whether listens should be collected from it (Enable new players).
  • These preferences can always be changed later from the settings.

In summary,
UpdatedUserFlow

Designing

The new onboarding flow designs will go through multiple iterations and reviews based on feedback from my mentors and MetaBrainz’s in-house designer.

Mockups & Visuals

  • Mockups: Figma Link
  • Screenshots & Visuals: (Images below)

Image

Key Design Considerations

  1. Consistency with Website – I tried to keep UI close to the ListenBrainz website to maintain a unified experience across platforms.
  2. Simplified Permissions Screen – Instead of multiple clicks for each rationale, all permissions are grouped into one screen, reducing friction.
  3. Smooth Animations – A moving Blob animation (like the one on the website) will be implemented to add a more interactive feel.
  4. Dark & Light Theme Support – Currently, the onboarding flow does not support dark mode. This will be fixed in the redesign.

Coding Implementation

Navigation Structure

I plan to keep all onboarding screens inside MainActivity using Nested Navigation. This brings several benefits:

  1. Seamless Transitions – Switching between Login, Permissions, and ListeningApps screens will be smoother compared to handling separate activities.
  2. Shared ViewModel – Instead of managing data across multiple activities, onboarding screens will share a common ViewModel, simplifying data handling.
  3. Scalability – Future additions to onboarding (like extra steps or interactive elements) will be easier to integrate.
@Composable
fun RootNavigation() {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = "onboarding") {
        onboardingGraph(navController)//Graph containing onboarding screens
        mainGraph(navController) //Current navigation setup in Main Activity(AppNavigation)
    }
}

Here’s a simple diagram of how navigation will be structured:

Image

Efficient Permissions Handling

ListenBrainz requires certain permissions to function optimally. Here’s what each one does:

  1. SEND_NOTIFICATIONS – Enables the app to send important alerts (e.g., new features, updates).
  2. ACCESS_MUSIC_AUDIO – Allows BrainzPlayer to access and play local music.
  3. READ_NOTIFICATIONS – Essential for Listen Submission, allowing the app to detect currently playing music.
  4. BATTERY_OPTIMIZATION – Ensures Listen Submission runs smoothly in the background without being killed by system optimizations.
  5. READ/WRITE_EXTERNAL_STORAGE – Required on Android 12 and below to access and play stored music files.

To manage these efficiently, I’ll introduce an enum-based approach, making it easier to check, request, and handle permissions dynamically. This will also simplify adding new permissions in future updates.

enum class PermissionsRequired(
    val permission: String,
    val title: String,
    val permanentlyDeclinedRationale: String,
    val rationaleText: String,
    val image: Int,
    val minSdk: Int, // Minimum Android version required
    val maxSdk: Int? = null, // Optional upper range
    val requiresSettingsNavigation: Boolean // Whether direct settings navigation is needed
) {
 
    ACCESS_MUSIC_AUDIO(
        permission = android.Manifest.permission.READ_MEDIA_AUDIO,
        title = "Access Music & Audio Files",
        permanentlyDeclinedRationale = "Without this permission, BrainzPlayer cannot play your local music files stored on your device.",
        rationaleText = "ListenBrainz requires access to your audio files so that BrainzPlayer can play your locally stored music seamlessly.",
        image = R.drawable.ic_music,
        minSdk = 33, // Introduced in Android 13
        requiresSettingsNavigation = false
    );
    //Other permissions here.

    fun isGranted(context: Context): Boolean { /* Check if permission is granted */ }

    fun requestPermission(activity: Activity) { /* Request the required permission */ }
}

Full rationale for all permissions can be found here.

Notify Updates

To ensure users always have access to the latest features and security updates, I will implement an in-app update notification system. This feature will check for updates on app startup and provide users with an option to update immediately or later, depending on the type of update.

Implementation Strategy:

  1. Google Play Store Updates:
    • I will integrate Google’s in-app update API, which provides two types of updates:

      • Immediate Updates:
        • Used for critical updates (e.g., API changes, security fixes).
        • Forces users to update before continuing app usage.
      • Flexible Updates:
        • Recommended for minor feature enhancements.
        • Users can continue using the app while downloading the update in the background.
    • These will be implemented using the following dependencies:

      implementation("com.google.android.play:app-update:2.1.0")
      implementation("com.google.android.play:app-update-ktx:2.1.0")
      
    • Users will also have the option to manually check for updates from the Settings screen.

2. F-Droid (GitHub) Updates:

Since F-Droid does not support Google’s Play Store APIs, implementing a standard update mechanism is a bit more challenging. Therefore, I’ll develop a custom update checker to ensure users can easily stay on the latest version.

My approach revolves around fetching the latest release version from GitHub’s API and comparing it with the installed version of the app. If there’s a newer version available, users will be notified and given clear options to update.

How the Update Check Will Work:

To check for updates, I will make a GET request to the following URL:

https://github.com/metabrainz/listenbrainz-android/releases/latest

I’ll request the response in application/json format to ensure a structured and efficient data fetch. The response will typically look like this:

{
  "id": 198543314,
  "tag_name": "2.8.1",
  "update_url": "/metabrainz/listenbrainz-android/releases/tag/2.8.1",
  "update_authenticity_token": "...",
  "delete_url": "/metabrainz/listenbrainz-android/releases/tag/2.8.1",
  "delete_authenticity_token": "...",
  "edit_url": "/metabrainz/listenbrainz-android/releases/edit/2.8.1"
}

The tag_name value (“2.8.1” in this example) represents the latest available version. By comparing this with the app’s installed version, I can determine if an update is necessary.

  1. General Update Flow:
    • The update prompt will only appear once per update (not on every startup).
    • The update process will be handled efficiently to avoid disrupting the user experience.
    • I will add proper logging to track update failures and improve the reliability of the update mechanism.

Refactoring Settings

Since the onboarding flow is being improved, certain settings options will be adjusted to maintain consistency:

  • Listening Apps Management – Users will now be able to modify their selected music apps directly from Settings.
  • App Updates – A new option will allow users to manually check for updates from Settings.
  • Permissions Management – Users will be able to re-enable declined permissions easily.

Error Log Submission

When users face a bug, they need a simple way to report it. The best approach is to collect recent logs in a text file and then attach that file to an email. This method ensures we capture enough details about the issue while allowing users to include screenshots or additional comments.

Steps for Error Log Submission

  1. Collect Recent Logs
    • We’ll capture logs using the logcat command.
    • Logs will be saved to a text file in the app’s external storage directory.
    • This ensures large logs are stored efficiently without losing information.
  2. Send Logs via Email
    • Users can submit the log file as an attachment.
    • We use Android’s Intent.ACTION_SEND to open an email client with pre-filled details.
    • This allows users to review and edit the bug report before sending it.

Implementation:

Saving logs to a File

fun saveLogsToFile(context: Context): File? {
    return try {
        val logFile = File(context.getExternalFilesDir(null), "logs.txt")
        val process = Runtime.getRuntime().exec("logcat -d *:V")
        val reader = BufferedReader(InputStreamReader(process.inputStream))
        val writer = BufferedWriter(FileWriter(logFile))

        var line: String? = reader.readLine()
        while (line != null) {
            writer.write(line)
            writer.newLine()
            line = reader.readLine()
        }

        writer.close()
        reader.close()
        logFile
    } catch (e: IOException) {
        null
    }
}

Send Logs via Email

fun sendLogsByEmail(context: Context, feedback: String, logFile: File?) {
    if (logFile == null || !logFile.exists()) {
        Toast.makeText(context, "Log file not found", Toast.LENGTH_SHORT).show()
        return
    }

    val uri = FileProvider.getUriForFile(context, "${context.packageName}.provider", logFile)

    val intent = Intent(Intent.ACTION_SEND).apply {
        type = "message/rfc822"
        putExtra(Intent.EXTRA_EMAIL, arrayOf((""))//Support email Ids
        putExtra(Intent.EXTRA_SUBJECT, "Bug Report with Logs")
        putExtra(Intent.EXTRA_TEXT, "$feedback. Please find the attached log file.")
        putExtra(Intent.EXTRA_STREAM, uri) // Attach the log file
        addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    }

    context.startActivity(Intent.createChooser(intent, "Send Email"))
}

Timeline

Phase 1: Initial Development & Core Onboarding Implementation

In this phase, I will focus on setting up the components of onboarding, permissions, and navigation.

Week Task Priority Technical Details
May 8 - June 1 Community Bonding [Medium Priority] - Finalize design reviews with mentors and aerozol. - Plan the nested navigation setup. - Discuss implementation approach for the removal of limurse library and any possible implications of removal.
June 2 - June 8 Setup Project & Refactor Navigation [High Priority] - Implement nested navigation in MainActivity . - Check the performance and avoid any backstack issues - Remove limurse onboarding library and replace it with a custom Compose-based solution. - Implement moving Blob animation.
June 9 - June 15 Implement Core Onboarding Screens [Critical] - Develop UI for onboarding screens explaining Listen Together, Reviews, and BrainzPlayer features. - Implement smooth animations (parallax effects, fade-ins, or Lottie) to enhance UX. - Apply checks to ensure that screen is visible to a newly onboarded user and not a logged out one.
June 16 - June 22 Permissions Handling – Step 1 [Critical] - Implement a modular permission handler using an enum class to manage all required permissions. - Create a scalable rationale dialog to explain why permissions are needed. - Implement logic to track when a user denies permissions twice and show an alternative UI.- Create all necessary UI components
June 23 - June 29 Permissions Handling – Step 2 [Critical] - Implement handling for SEND_NOTIFICATIONS, ACCESS_MUSIC_AUDIO, READ_NOTIFICATIONS, BATTERY_OPTIMIZATION, and STORAGE. - Ensure seamless navigation between permissions UI and system settings. - Test across multiple Android versions (Android 12, 13, 14,15) for compatibility.
June 30 - July 6 Listening Apps Selection Screen [High Priority] - Develop UI for selecting apps from which Listen Submissions will be collected. - Implement the login in OnboardingViewModel - Ensure that users can modify selections later in settings. - Make this screen navigable from settings and handle the state of the current user (onboarded or not).
July 7 - July 13 Testing & Refinement Before Midterm [Medium Priority] - Fix bugs from onboarding & permissions handling. - Improve UX based on mentor feedback. - Ensure onboarding flow does not break if user denies a permission and retries later.

Midterm Evaluation (July 14 - July 18)

Focus on submitting midterm evaluation, bug fixes, and feedback from mentors.

Phase 2: Login, In-App Updates & Settings Refactor

This phase focuses on refining onboarding, implementing sign-in, in-app updates, and refactoring settings.

Week Task Priority Technical Details
July 19 - July 25 Revamped Sign-In Screen [High Priority] - Implement redesigned Login Screen with WebView.- Handle login failures gracefully (network errors, incorrect credentials, etc.).
July 26 - August 1 In-App Update Prompt [High Priority] - Implement logic to fetch the latest version from Play Store or GitHub (for F-Droid users). - Show a one-time update prompt on app startup if a new version is available. - Allow users to check for updates manually via settings.
August 2 - August 8 Refactor Settings for Onboarding Integration and Submitting Error Logs [Medium Priority] - Update Listen Submission settings to reflect user choices made during onboarding. - Add an option to disable battery optimization in app settings. - Ensure that permission preferences are properly saved & synced in AppPreferences -Add additional option to “Report a Bug”
August 9 - August 15 Testing & Bug Fixes for Completed Features [Medium Priority] - Conduct extensive UI/UX testing for all onboarding components. - Fix edge cases where a user exits onboarding midway. - Gather feedback from our ListenBrainz community.

Final Evaluation, UI Tests & Polishing

Last phase to refine UI/UX, collect feedback, and prepare for final submission.

Week Task Priority Technical Details
August 16 - August 22 UI/UX Feedback & Final Adjustments [ Medium Priority] - Collect feedback from aerozol & mentors on design consistency. - Test onboarding across different screen sizes (phones, tablets).
August 23 - August 25 Final Submission Preparation [High Priority] - Write a detailed technical report on all implemented features. - Clean up code, remove unused dependencies, and optimize performance. - Prepare & submit final GSoC evaluation. - Work on Extras if time permits.

Extras

These are some additional features I’d love to work on if time permits:

  1. Push notifications when read notification permission is removed – As mentioned in the overview document, we follow the philosophy “Never Give Up”. If the app loses notification access, I will implement push notifications to remind users that Listen Submissions won’t work properly without it.
  2. Deleting listens directly from the app – Right now, if users want to remove a listen, they have to open a browser and do it manually. This breaks the experience. I want to add an option to delete listens within the app itself, making the process seamless. I’ll use the ListenBrainz API endpoint for this: POST /1/delete-listen

Post-GSoC Plan

Even after GSoC ends, I want to keep contributing to ListenBrainz Android. If for some reason I can’t finish the extras during GSoC, they’ll be my first priority afterward. Apart from that, there are a few areas I’d like to improve:

  1. Better Listen Submission controls – Expanding on the “delete listens” feature, I want to improve how users manage their listening history.
  2. Universal Search – Right now, the app supports user search, but it would be great to search for playlists, albums, releases, and artists as well.
    • For artists, albums, and releases, I’ll use the MusicBrainz Search API.
    • For playlist and user search, I’ll use these ListenBrainz API endpoints: GET /1/playlist/search and GET /1/search/users/
  3. Improving profile screen performance – The profile screen currently does not have pull to refresh in Listens, Taste and Stats screen. I would like to implement the same to fetch latest data (Especially useful to fetch latest listens).
  4. General UI/UX improvements – There are always small tweaks that can improve the app’s usability. Based on user feedback, I’ll keep refining the onboarding flow, permission management, and player UI.

And of course, I’ll keep participating in discussions and contributing to future updates. Metabrainz has a great open-source community, and I’d love to stay involved long-term.

Community Affinities

Tell us about the computer(s) you have available for working on your SoC project!

I’ll be using my Lenovo IdeaPad Gaming 3 15IAH7, which has a 12th Gen Intel(R) Core™ i5-12450H @ 2.00 GHz processor and 16GB RAM. It’s more than capable of handling Android development smoothly.

When did you first start programming?

I first started coding in 8th grade with Java. In 11th grade, I picked up Python, and then during my first semester in college, I explored C and C++. Eventually, I found Kotlin, and I absolutely love working with it now.

What type of music do you listen to?

I mostly enjoy soulful Bollywood music. Some of my favorite artists include Iqlipse Nova, Arijit Singh, and Anuv Jain.

A few of my favorite MBIDs are:

  • 2ed432c1-c13c-461d-8aab-dd8ebac9ad41
  • 83f4e9da-9901-451f-a6c7-94dad3414f34
  • a2f76f56-e53b-4afc-8ff0-b0dd80b1fd91

What aspects of the project you’re applying for interest you the most?

I’m applying for ListenBrainz Android, and the most exciting part for me is how ListenBrainz is evolving into a community-driven platform—almost like a social media app, but for music. The ability to share, review, and connect with others over music makes it feel special, and I love that the Android app can help expand its reach even further.

Have you contributed to other Open Source projects?

No, ListenBrainz Android is my first deep dive into Open Source, and I’m really excited about it!

What sorts of programming projects have you done on your own time?

I’ve worked on several Android projects, exploring libraries like:

  • CameraX for camera integration
  • TensorFlow Lite for lightweight ML models
  • Firebase for authentication and real-time databases
  • Koin for dependency injection
  • Room for local database management

Apart from Android, I’ve also built some projects with PHP & MySQL and a few using Django. One of my projects is a news app that integrates ML for content summarization.

How much time do you have available, and how would you plan to use it?

I can dedicate 35-40 hours per week to the project, fully focusing on development. Since I will be on summer vacation, I will be available during this period without any academic distractions. If I get extra time, I’d also like to help out with other issues in the project and contribute beyond my proposal.

4 Likes

Hi great proposal overall. Few pointers:

  1. Login will be the first screen the user will see.
  2. I would need a bit more context on how you will achieve fetching updates from GitHub.

Some expectations beforehand:

  1. We expect the new onboarding library to be flexible.
  2. We expect going back and forth between pages of onboarding being handled properly.
  3. Permission handling component should be made such that, if in future, we were to add a new permission, it should behave as other permissions. We want a plug and play system for permissions.

Additions:

  1. I case of errors, can we include submit logs button somewhere in the onboarding. Just a small button.
  2. Also another onboarding screen which explains where to submit logs from.
1 Like

Thank you for your feedback! I’ve made the necessary updates based on your suggestions.

Login Screen Update

I have updated the Figma designs so that the Login screen now appears immediately after the introduction screens, before the Permissions and Listen Submission screens. This ensures a smooth user flow.

F-Droid (GitHub) Updates:

Since F-Droid does not support Google’s Play Store APIs, implementing a standard update mechanism is a bit more challenging. Therefore, I’ll develop a custom update checker to ensure users can easily stay on the latest version.

My approach revolves around fetching the latest release version from GitHub’s API and comparing it with the installed version of the app. If there’s a newer version available, users will be notified and given clear options to update.

How the Update Check Will Work:

To check for updates, I will make a GET request to the following URL:

<https://github.com/metabrainz/listenbrainz-android/releases/latest>

I’ll request the response in application/json format to ensure a structured and efficient data fetch. The response will typically look like this:

{
  "id": 198543314,
  "tag_name": "2.8.1",
  "update_url": "/metabrainz/listenbrainz-android/releases/tag/2.8.1",
  "update_authenticity_token": "...",
  "delete_url": "/metabrainz/listenbrainz-android/releases/tag/2.8.1",
  "delete_authenticity_token": "...",
  "edit_url": "/metabrainz/listenbrainz-android/releases/edit/2.8.1"
}

The tag_name value (“2.8.1” in this example) represents the latest available version. By comparing this with the app’s installed version, I can determine if an update is necessary.

Onboarding & Permission Handling

  • The new onboarding library is flexible, allowing easy addition/removal of screens.
  • Users can navigate back and forth smoothly between onboarding screens.
  • Permission handling is now modular—adding a new permission is as simple as updating an enum and defining a function to check its availability.

Additional Features

  • “Submit Logs” Button: Added to the Login screen, so users can report issues during onboarding itself.
  • New Onboarding Screen: A 4th introduction screen has been added to explain where users can submit logs from later.

Error Log Submission

When users face a bug, they need a simple way to report it. The best approach is to collect recent logs in a text file and then attach that file to an email. This method ensures we capture enough details about the issue while allowing users to include screenshots or additional comments.

Steps for Error Log Submission

  1. Collect Recent Logs
    • We’ll capture logs using the logcat command.
    • Logs will be saved to a text file in the app’s external storage directory.
    • This ensures large logs are stored efficiently without losing information.
  2. Send Logs via Email
    • Users can submit the log file as an attachment.
    • We use Android’s Intent.ACTION_SEND to open an email client with pre-filled details.
    • This allows users to review and edit the bug report before sending it.

Please keep adding changes to the original proposal.

Yes, I have updated the same in the proposal.
Here is the pdf link.