Skip to content

[Feature] Custom storage location for downloaded music #160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
pmprog opened this issue Oct 4, 2024 · 16 comments
Open

[Feature] Custom storage location for downloaded music #160

pmprog opened this issue Oct 4, 2024 · 16 comments
Assignees
Labels

Comments

@pmprog
Copy link

pmprog commented Oct 4, 2024

Hi,

Great app, thanks.

Would it be possible to allow the user to select where to store downloaded files. At the minute it seems to be putting on device, which my phone has very little, but I have an SD card that's got plenty of space

Regards

@icefields
Copy link
Owner

Hello,
Allowing an external location is on my roadmap, but it’s currently a low priority. The downloaded songs are fully synced with the internal database, which is also synchronized with the server database. This setup ensures data consistency and supports statistics tracking, scrobble, likes, ratings, adding to playlist. Allowing users to manage the files manually would require a resource-intensive scan at startup to check for consistency, which would slow down the app, since I cannot rely on users and trust them not to modify the saved files.

I’m considering solutions for this, but again, it’s a low priority for now since I'm focused on other features.

@pmprog
Copy link
Author

pmprog commented Oct 8, 2024

Hi,

Thanks for the reply. I appreciate your focus.

I haven't done much Android, and certainly haven't used Kotlin, but I went looking; but I might be wrong, so feel free to correct me.

Your code for saving the files seems to boil down to context.filesDir, which equates to context.getFilesDir() in Java.

According to this document in the App-specific files section, getFilesDir() has a sibling called getExternalFilesDir(), which, if I read correctly, works exactly the same, but is just stored on the external storage
https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String)

So you could possibly get away with a toggle button of "Use External Storage", and just use an if to call filesDir or externalFilesDir respectively?

I've had a bit of hassle trying to build it locally, had errors about gradle versions. I did manage to finally get it to build, but I'm not sure what the consequences are if I committed those even if I got the changes done myself?

Cheers

@icefields
Copy link
Owner

hi,
I think there's a misunderstanding here. I know exactly how to do it, that's not the issue at all. The reasons I'm not doing it are purely architectural in nature, and I explained them in the previous message (also quoted below).

The downloaded songs are fully synced with the internal database, which is also synchronized with the server database. This setup ensures data consistency and supports statistics tracking, scrobble, likes, ratings, adding to playlist. Allowing users to manage the files manually would require a resource-intensive scan at startup to check for consistency, which would slow down the app, since I cannot rely on users and trust them not to modify the saved files.

If you want to do it yourself you're welcome to try, the code is fully open source and fairly documented, but the changes are complex and affect data, domain and presentation layers, so there's going to be a good amount of code to write, and changes to the sqlite database schema to perform (taking also good care of the db schema migration, to maintain backwards compatibility and not break the app for users).
If you're thinking about committing to this repo, there are strict development guidelines to follow, the project follow Clean Architecture and SOLID principles strictly. I wrote some basic notes about it here: https://power.ampache.dev/contributing.html .

Thank you for trying the code!
Cheers

@pmprog
Copy link
Author

pmprog commented Oct 9, 2024

Maybe there is a misunderstanding, because how I understand getExternalFilesDir is exactly the same as getFilesDir (which you're using), it'll just store on the SD card, not the internal storage, but still restricted. The documentation says "These files are internal to the applications, and not typically visible to the user as media", so that should alleviate you concerns of users modifiying files?

I didn't think it would require that much to change, as the only references to the path is within the StorageManagementImpl.kt file, and obviously add some setting. But considering I couldn't work out how to add another setting visually to the setting page (unless it was just the designer in AndroidStudio that was failing to update properly?), I'm not sure if I'll get very far.

Regards

@icefields
Copy link
Owner

icefields commented Oct 9, 2024

yes, keeping the files internal to the app would reduce the work (but that's not the way I'm planning on doing it, I would want to allow full control for the user).
You still need to check if the card is mounted, and if it's not? what's the strategy? This needs planning. At the very least the UI would need a warning, with some actions (try again, exit, ...etc), so that's a new design that I need to run through my designer. Also what's the strategy in that case with the "zombie" items in the database when the card is unmounted? Do I remove them? Do I keep them there taking space, hoping the user will remount the sd card?

As for settings management, these are stored in an internal SQLite database. Adding a new option means we’ll need to add a column to the table, necessitating a database migration to the new schema. The database operates in the data layer and communicates updates to the rest of the app through Flows. We’ll need to implement a method in the settings interface and then integrate it into the data layer.

Additionally, the presentation layer will need adjustments to include the new option, which will also require collaboration with my designer.

While I do plan to implement support for external storage in the future, I must prioritize more urgent tasks at the moment. Given that modern phones typically come with 512GB of storage by default, the need for custom storage locations has diminished over time, and it's not a priority anymore.

When I decide to implement this feature, I plan to use non-internal custom directories, giving users full control over their music files. Opting for a different approach at this stage would lead to writing a lot of throw-away code and would slow down the development of the features I’m currently focused on.

@icefields icefields changed the title Feature Request: Choose storage location for downloads [Feature] Custom storage location for downloaded music Oct 9, 2024
@icefields icefields self-assigned this Oct 9, 2024
@pmprog
Copy link
Author

pmprog commented Oct 9, 2024

That's fair enough. Thanks for considering it.

My phone has 8GB (with about 5GB of that used by Android), so basically nothing before you even install any apps...
I might just have a go at building with StorageManagementImpl switched to use the External property. I won't need to care about card mounting etc. because it never changes, and if I make it a hard switch, I won't need to bother with any GUI/Settings updates too.

I obviously understand this wouldn't be suitable for the official app though.

Regards

@icefields
Copy link
Owner

I asked around and to be honest with you, I didn't realize phones with such a small storage were still around.
I might have a way to make this change for you in a non-invasive way, respecting the Liskov substitution principle and reducing the side-effect at the minimum.
I could either create an extension to that class or use a delegate (I'll probably go with the delegate), so when I decide to implement it properly all the code to remove is in the same spot and won't affect the rest of the app.
Give me a few days to develop it and to do some tests. If you want to test during development, contact me on Telegram or Mastodon. Links in the README of the repo.
If everything goes well, and I've done enough testing (again, if you want to help testing, dm me), the change will be available in the next release.
Let me know if you need more assistance.

@pmprog
Copy link
Author

pmprog commented Oct 10, 2024

Well, to be fair, they're probably owned by people like me who doesn't see a point in buying a new phone just because somebody brought a new one out :)

Honestly, don't just push it up your list because I'm running a 6 year old phone if you've got more important stuff to fix. I can continue to use multiple media players, it's not the end of the world.

As an aside, I'm afraid I use neither Telegram nor Mastodon

Regards

@icefields
Copy link
Owner

of course, I was just referring to statistical data. If people don't see the point of buying a new phone, that's a totally legitimate choice.
The change I will try to make should be simple enough to at least have users enjoy the app without having to worry about device space.
I need to verify this, but testing from the emulator getExternalStorage, I think only works if your SD is installed as system storage and not as an expansion.

Anyway, I'm not trying to convince anyone here, but you brought up a cool topic that I enjoy chatting about, I want to give you my thoughts on this, those are the PERSONAL reasons I buy new hardware:
Security, creativity, performance, hardware deprecation, battery degradation and technological advancement.

DEPRECATIONS - TECHNOLOGICAL ADVANCEMENTS
The deprecation of old hardware by various development SDKs alone is a compelling reason to upgrade (for Power Ampache 2 I use the latest most updated Android SDKs). For instance, the notification system I use for the music player, based on newer Android SDKs, behaves oddly in 'compatibility' mode on older phones. I want to avoid that issue for myself—I prefer having the best, cutting-edge technology.
That’s also why I’m a passionate Arch Linux user.

PRIVACY/SECURITY
Everyone has their own personal threshold for threats, and I’ve drawn the line against the overreach of big tech by exclusively purchasing Pixel phones wich I then wipe out and install GrapheneOS on. I only use de-Googled devices with GrapheneOS or CalyxOS, as these ROMs are designed specifically and ONLY for Pixel hardware. I don’t trust other ROMs because they often don’t lock the bootloader after installation, and their development processes seem less streamlined. In contrast, GrapheneOS and CalyxOS have robust communities focused on privacy and security, with thorough testing and scrutiny. This approach already excludes devices prior to the Pixel 4 (or possibly the 5 at the moement), which come with at least 256GB of storage and 3GB of RAM.

CREATIVITY - EXTENDED POSSIBILITIES
At my core, I’m just a wannabe-creative tech enthusiast who loves innovation. A phone with 8GB or even 16G of RAM opens up countless possibilities for development and creativity. Fast internal storage, as opposed to a slow SD card, allows me to store more data and complete tasks much more efficiently. With ample storage, I can easily sync with Nextcloud, download music, and so much more.

At some point, the critical questions to consider are: Is this old hardware affecting my creativity? Is relying on outdated SDKs in compatibility mode worth it? Is the frustration from using outdated devices worth the cost of a new phone? Is the risk of falling behind in technology justified? And ultimately, how much is my time worth?

I had my current phone for 5 years now, still great, the simple fact that I don't have any google installed extended the battery life to almost a week, and performance is still fine. But I think as soon as one of my favourite roms starts supporting the AI chip in a private way, I'll get the new device.

@pmprog
Copy link
Author

pmprog commented Oct 12, 2024

I don't want to totally derail the issue, but as there's not much to add, and you're happy to have a conversation about tech, I'll participate.

When it comes to tech advancements. I'm afraid I'm kind of on the opposite side. In my workplace, we have to develop software for some hardware which only runs Android 5... There's no choices, it's just Android 5. Then when certain updates came out that removed the Android 5 SDK off our development machines and told us it wasn't "supported" was very much an issue. The devices aren't "public" facing, so the app doesn't need the "latest and greatest", it just needs to work; and the forced update to systems and development is problematic.
Prior to the Android 5 devices, we were running Windows Mobile 6 devices... in the end I had to create Windows 7 VM's to run the correct version of Visual Studio to even be able to support them.

Privacy-wise, I'm in agreement. I bought a PinePhone in the hopes to escape a number of big tech. Unfortunately, most of my family and friends use WhatsApp, and there's the banking apps, so I failed to escape. I thought the Motorola phones would be pretty well supported with some of the alternative OSes, but the particularly one I got didn't seem to be. Need to check better when I come to upgrade it next.

I find it interesting you talking about old hardware affecting your creativity, where-as I look more to the old vintage computers/consoles for development (Gameboy Advance, Commodore 64, Commodore Amiga). They are technically more restricted, but still interestingly capable.

@icefields
Copy link
Owner

@pmprog I added the option to download the music to the SD card in the newest version of the app.
Here's the release page:
https://github.com/icefields/Power-Ampache-2/releases/tag/v1.00-69
Give it a few days for the PlayStore version, and about 6 days for the FDroid version.

A screenshot:
image

@pmprog
Copy link
Author

pmprog commented Dec 1, 2024

Great, thank you. My server fell over the other week, so I'm just in the process of rebuilding, but I'll give it a try as soon as I can.

@pmprog
Copy link
Author

pmprog commented Dec 19, 2024

Hi,

Gave this a test, and even with it ticked, it saved to the local device, rather than the SD card.
Also, when I tried to download two albums, it only downloaded the first track of each album.

I'm on version 1.00-70-fdroid (Added 09/12/2024), which is the latest at time of writing

Regards

@icefields
Copy link
Owner

hi, thanks for testing.
Are you sure your SD card is mounted as system storage and not as external storage?
For the downloads, that sounds like bug, do you have logs (settings -> enable logs) ?

@pmprog
Copy link
Author

pmprog commented Dec 20, 2024

Hi, I'm afraid I don't know what you're talking about.
There are no mounting options for the SD card. It's just mounted, or not. The phone is Android 10, if that makes a difference.
I can just download a playlist at a time for now, that's not the end of the world, if you want to focus on more important things, and I might consider a new phone in the new year.
Feel free to keep or close this ticket.
Thanks for looking

@icefields
Copy link
Owner

@pmprog on android devices, when you insert a new card, the system asks if you want the card to be mounted as internal/system storage or as a regular sd card. For now downloads on sd card only work if it's mounted as internal storage.
I will implement the other way as well at some point in the future, it's a bit more complex because there are more edge cases, chances of user error, and I will have to ask for write permissions.

Here's a quick guide on how to mount the card as system storage (be careful if you try, you'll lose your SDcard data, since the card will be formatted again).

image
image
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants