Skip to content

Add android app#62

Open
paytonjjones wants to merge 17 commits intopganssle:mainfrom
paytonjjones:add-android-app
Open

Add android app#62
paytonjjones wants to merge 17 commits intopganssle:mainfrom
paytonjjones:add-android-app

Conversation

@paytonjjones
Copy link

Thanks for building this great tool! I've been using it with my daughter and she really enjoys it, she calls it the "piano game" :)

I wanted to have this available on my phone as a persistent Android app. Android WebView makes this relatively straightforward — I just had to work out some bugs to get everything working properly.

Importantly, this PR does not alter any of the functionality of the original web app.

Summary:

  • make android-setup runs Jekyll with an environment flag to create the Android app under android-wrapper/ (built files are in .gitignore to prevent file duplication)
  • Based on that environment flag, a handful of if/else statements in index.html handle minor differences
  • Tone.js causes some thorny issues with WebView, so for Android I've restricted to the pre-recorded MP3 file sounds and made some changes to avoid calling Tone.js
  • The committed files under android-wrapper/ are 99% boilerplate generated by Android Studio

After calling make android-setup, you can open android-wrapper/ as an Android Studio project and sideload the app onto your phone.

Copy link
Owner

@pganssle pganssle left a comment

Choose a reason for hiding this comment

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

Thank you for the PR, this is something I've been wanting to do for a long time but haven't gotten around to. However, as I've mentioned in some of the inline comments, I think that this particular approach is not going to work because it only works with the "legacy" mode, which wasn't intended to be used for new users and doesn't support the full range of chords.

I also think that my preferred workflow here would not be to check in the app but rather to set up GH Actions to generate the files for us and automatically produce APK files.

I am also not 100% clear — does this bundle all the MP3 files into the APK, or does it still try and fetch them from somewhere? The only real advantage that a dedicated app would have over the PWA would be if it eliminates the problem that the PWA has where sometimes, randomly, you need to be online to access it (though I also wonder if there is another way to fix this).

@@ -0,0 +1,6 @@
{
Copy link
Owner

Choose a reason for hiding this comment

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

I think you may want to add this to your global .gitignore and remove it.

Ditto for .vscode/settings.json.

Copy link
Author

Choose a reason for hiding this comment

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

Good call, I've removed these and added them to the .gitignore

.ruby-version Outdated
@@ -0,0 +1 @@
3.2 No newline at end of file
Copy link
Owner

Choose a reason for hiding this comment

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

I don't know what this does, but it doesn't seem related to the Android app portion.

Copy link
Author

Choose a reason for hiding this comment

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

This was for rbenv — it's not necessary and I've deleted it (and I'm using brew for Ruby now in any case).

Gemfile Outdated

gem "json", "~> 2.7"
gem 'csv', '~> 3.0'
gem "logger"
Copy link
Owner

Choose a reason for hiding this comment

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

Are these changes necessary because you are adding more platforms? If they are unrelated changes maybe a separate PR would be better.

Copy link
Author

Choose a reason for hiding this comment

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

I've removed these

@@ -0,0 +1,5 @@
# Android WebView disables fetch(), which is used in Tone.js when legacy=false
Copy link
Owner

Choose a reason for hiding this comment

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

I think this is actually a non-starter for this concept if we can't get it working. The "legacy" instruments aren't supported all the way to the end of the sequence, I only kept it in place because there were kids already using the app and I wanted to give them the option.

If we cannot use Tone.js, I think we'll need to do a bigger overhaul on the app to get it working for Android — I've been largely unsuccessful at simply invoking Tone.js to generate .mp3 files, but I think that if that were possible, doing it as part of the Android build and bundling the files into the APK file would be better.

Copy link
Author

Choose a reason for hiding this comment

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

Per your suggestion, I was able to get Tone.js working to generate .mp3 files all the way to the end of the sequence.

To accomplish this, I added a few make commands that use a local browser session to run Tone.js and produce the audio files. This was a bit tricky to set up, and I expect it could be brittle for other contributors (since it depends on local browser automation).

To avoid making this a build requirement, I committed all of the generated .mp3 files directly to the repository. That way, developers don’t need to regenerate them unless we add new instruments or change existing ones.

One small adjustment I made in the process was to replace # in filenames with Sharp. The # symbol was causing URL-encoding issues. I’ve updated references throughout the project to reflect that change (as we need to swap back to # for Tone.js).

@@ -0,0 +1,15 @@
*.iml
Copy link
Owner

Choose a reason for hiding this comment

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

This Android wrapper is entirely generated code, right? I usually don't check in generated code.

Copy link
Author

Choose a reason for hiding this comment

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

I'm new to Android development so I initially had the same question.

After looking into it, these files are indeed meant to be committed. Much of the Android wrapper is scaffolding created via Android Studio (so “generated” in the sense of initial setup), but it is not transient build output. They’re closer in spirit to config or build-system files than to compiled artifacts. This SO question has some good discussion about it: reference.

Also, you’ll notice some image resources such as src/mipmap-hdpi/cim_logo.webp. Those aren’t automatically generated — I added them manually, and they’re required for a successful Android build.

@paytonjjones
Copy link
Author

paytonjjones commented Nov 6, 2025

Hi Paul! I’ve gone through all your comments and addressed the outstanding issues.

The main update is a new flow for pre-generating .mp3 files for the entire sequence. This process is a bit finicky (it relies on a local browser session), so my preference is to commit the generated files directly to the repository. That way, developers don’t need to reproduce the process unless we add a new instrument.

A nice side effect is that this also fixes the “legacy” instruments for the web version through the full sequence.

These are bundled into the APK; the Android app is fully offline.

As for the APK-related files: the ones currently committed aren’t “generated” in the sense that they can be easily reproduced via a GitHub Actions script, so they do need to be versioned. The truly generated components, such as build/ and assets/, are already covered by .gitignore and excluded from version control. They can be reproduced for new developers with make android-setup.

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.

2 participants