Skip to content
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

Target SDK version is still 29, but must be 30 or higher #178

Closed
arjanvlek opened this issue Oct 30, 2021 · 4 comments
Closed

Target SDK version is still 29, but must be 30 or higher #178

arjanvlek opened this issue Oct 30, 2021 · 4 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@arjanvlek
Copy link
Contributor

arjanvlek commented Oct 30, 2021

No idea if the current development team is aware or not, but starting in 2 days, this app must target at least SDK version 30 or higher, otherwise it cannot be updated in Google Play anymore.


Schermafbeelding 2021-10-30 om 16 37 54

@arjanvlek arjanvlek changed the title Target SDK version is 29, but must be 30 or higher Target SDK version is still 29, but must be 30 or higher Oct 30, 2021
@adhirajsinghchauhan adhirajsinghchauhan added enhancement New feature or request help wanted Extra attention is needed labels Oct 30, 2021
@adhirajsinghchauhan
Copy link
Member

adhirajsinghchauhan commented Oct 30, 2021

Correct, but we can't bump to 30 (or 31) because the app's download functionality would no longer work as it should, owing to severely restricted scoped-storage rules.

Technically the app will still be able to download OTA ZIPs (because it uses its own app-directory), but it won't be able to move them to the correct location that's required by the system's "Local upgrade" screen: the topmost directory of internal storage (often called the "root" directory — unrelated to device root status). This is because scoped-storage doesn't allow apps to request permission for the topmost directory at all (not the Downloads directory either).

There are a few options, but none of them are ideal:

Request the MANAGE_EXTERNAL_STORAGE permission (easiest to implement)

    Drawbacks:

  • It needs special approval from Google, and I'll need to talk to Googlers beforehand to see if it's viable (you can request this only after publishing an update with the permission included in the manifest I think, so it's safer to ask first). Even if we are allowed this permission, it comes with the risk of being removed from the Play Store for obscure reasons (it's happened to a lot of innocent apps, mostly due to error and lack of communication).
  • This permission grants full access to all files to the app that holds it, which makes it appear dangerous to users (and for good reason). Yes, the app is open-source and its releases (APKs uploaded to GitHub) can easily be verified to be authentic by those who know how to do so (we upload Android app bundles to the Play Store, but otherwise it's built from the exact same code at the same time). But these aren't enough to make the community immediately trust the app with this permission — there'll always be friction.
Don't move the ZIP to the topmost directory at all, for API >30 (easy to implement)

    Drawbacks:

  • Terrible UX. The user will have to manually move the file every single time from our internal app-specific directory (/Android/data/<package-name>/files). It's a pain to navigate, even if you're tech-savvy and can generally complete mundane actions quickly.
  • If we create a custom directory then it makes it a tad easier but it's still not best for the user, in terms of ease-of-use. If "Local upgrade" could accept ZIPs from anywhere then this wouldn't be a problem for us at all. Recovery seems to allow picking files from anywhere, but asking mainstream users to use recovery is a no-go.
Request permission for each ZIP that the user downloads (difficult & tricky)

    Drawbacks:

  • User can change filename if they wish, but the API doesn't inform the app about it. So later on if we try to check the existence of this ZIP to update UI (show a "Delete" button for example), it can't be done because we don't know the name of the file the user chose.*
  • In local development, this is not reliable at all. SAF APIs are absolute garbage for long-running tasks.
    For one, the permission seems to expire after an unknown period, even after persisting the permission. Persisted permissions are supposed to last until the next restart (meaning we have to re-request it, much to the annoyance of the user), but this doesn't seem to work for topmost files, which results in a lot of generic file IO exceptions while the app/service is alive.
  • Terrible UX. The app is meant as an easy-to-use solution to skip rollout queues, with minimal effort from the user, but this goes out the window if we start surfacing permission dialogs (and the explainer text that should be shown before it) every single time.

There may be more alternatives but these are the main ones. It's been a while since I've actively worked on any of these, because it was frustrating to workaround the nonsense that is SAF. So until I find the energy to revisit this, or until someone finds a neat solution to this, the app won't receive updates.

Not being able to push an app update until we solve this major roadblock might not be a bad thing, because as of v5.5.0 (latest release at the time of this comment) the app has only one "crash event" listed in Firebase; an NPE thrown because apparently the internal storage directory doesn't exist, which is just absurd:

val externalFilesDir = context.getExternalFilesDir(null)!!

a

@bluehomewu
Copy link
Contributor

I talked with @AnonymousWP few mintues ago, I have some ideas.

I know a lot of developers leave Google Play Store because this API reason.

Maybe use root permission can do it, for non-root users make some hints.
If still want though Play Store to unlock FREE-AD service, you can try to make an unlocker.
Like this application.
https://play.google.com/store/apps/details?id=eu.thedarken.sdm.unlocker

Unlock FREE-AD service , and pair with main app.
And push main app update to GitHub release page.
Let users download from GitHub.

Or....
Using this project. And make some modified.
https://github.com/RikkaApps/SaveCopy

Hope I can help you, I don't have too much coding experience with Kotlin, I can't give some useful code.

Have a nice day.

Edward.

@adhirajsinghchauhan
Copy link
Member

adhirajsinghchauhan commented Jan 11, 2022

The initial versions of this application were not beginner friendly, and over the years we've made several improvements to make it more accessible — even to users who aren't attuned to the technical aspects of updating a phone.

Managing storage via root access would be a major hindrance to such users, maybe even to experienced folk. So whatever solution we go with, it will for sure not involve root bypasses. In fact, we've been thinking of removing the app's current root-related features since they're largely unnecessary. One of them is to automatically hide "incremental" update methods, since they don't work on rooted devices (or ones with an unlocked bootloader, in some cases). The other root-feature is automatic installation via recovery, but for a long time this method has proven to be useless. Using Magisk's "flash to other slot" method is far more effective.

Anyway, all that needs to be done is choosing the best solution after exhausting all possibilities. I have already spent quite a bit of time thinking & testing (see previous comment), and I feel the second option (don't download to the topmost directory) is the easiest. Our installation guides would need to be edited, and it would require users on API>30 to do one extra step. Not perfect, but does the job. If we find nothing better, I will also talk to some Googlers I know and see if option 1 is a good idea.

However, as I've said before, it has been some time and I'm sure I haven't explored everything yet. Thank you for your idea — I was hoping for others to suggest alternatives I haven't considered. Publishing releases on GitHub without changing target SDK would probably work, but at the moment I don't feel it's necessary. For any bugs the app has (e.g. "unsupported" warnings for 9-series on OOS12), the app's "advanced mode" feature is a saving grace to bypass those bugs.

EDIT: ad-free unlocks is a not a concern at all, it's only the fact that scoped storage doesn't allow downloading to the topmost directory.

Let's discuss more on Discord, and post our conclusions here.

@arjanvlek
Copy link
Contributor Author

Small addition to option 1: If you request the MANAGE_EXTERNAL_STORAGE permission, the user must - probably once - be redirected to Settings to manually allow the app to access all files. Probably not too bad, but in my opinion worth to be mentioned.

Example from Acrobat (https://www.adobe.com/devnet-docs/acrobat/android/en/settings.html?highlight=star):

image

image

adhirajsinghchauhan added a commit that referenced this issue Mar 18, 2022
https://github.com/oxygen-updater/oxygen-updater/releases/tag/oxygen-updater-5.7.1

Highlights:
- v5.6.0 wasn't published to the Play Store, but this release is!
- Fixed #189, #178
- Updated dependencies
bluehomewu pushed a commit to bluehomewu/oxygen-updater that referenced this issue Mar 20, 2022
bluehomewu pushed a commit to bluehomewu/oxygen-updater that referenced this issue Mar 20, 2022
https://github.com/oxygen-updater/oxygen-updater/releases/tag/oxygen-updater-5.7.1

Highlights:
- v5.6.0 wasn't published to the Play Store, but this release is!
- Fixed oxygen-updater#189, oxygen-updater#178
- Updated dependencies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants