This is why no one ever pays more than a couple bucks for a mobile app. That would be a terrible investment, as the app could break at any time!
Similarly, this is why mobile will never be a good platform for traditional single-player video games.
This is why no one ever pays more than a couple bucks for a mobile app. That would be a terrible investment, as the app could break at any time!
Similarly, this is why mobile will never be a good platform for traditional single-player video games.
> Since this app hasn’t been updated within the last three years [...] it has been removed from the App Store
I also greatly dislike how iOS takes the backwards approach of offloading backward compatibility as a yearly support burden multiplied across every developer - rather than maintaining it in the OS.
Platforms are supposed to absorb developer pain for multiplicative benefit - not the other way around.
Among modern operating systems, iOS is probably the worst in terms of backwards compatibility but it’s also one of the most pleasant to develop for — UIKit/Cocoa is unrivaled in terms of both breadth and depth. One can easily build a top class iOS app with few or no third party dependencies, which is not the case on most other platforms. I don’t think that’s a coincidence… if the iOS dev team were encumbered with maintaining backwards compatibility for upwards of a decade it would be much more difficult to build such a complete and polished toolkit.
I wouldn't even be opposed to older apps running in some sort of seamless-to-the-user virtual machine.
It blows my goddamn mind.
It's not as good as Windows' back compat, no. But then again nothing is, as that's the only platform concerned with preserving not just API compatibility but bug compatibility.
Every version has random will-be-breaking changes that get held off if your app was compiled before said version came out, but there's only a release or two before the change starts to ignore your compiled version (for example, when a massive permissions change comes down the pipe, any app that's compiled against the newest SDK breaks immediately, and apps that were compiled against older ones just get to break next release)
And just like any mobile platform, apps heavily rely on the OS to provide UI widgets and layout. So even design language changes can (and often do) break the UI.
-
What you're probably seeing is what developers are forced to work around: the fact that everyone is stuck targeting ancient versions of Android because Android users have just accepted their devices never getting OS upgrades.
Android Studio will still default to targeting a minimum SDK version of API 25. Android 5.0. From November 12 2014.
The situation is so bad that Google removed it from their dashboard (https://developer.android.com/about/dashboards) and buried it in the IDE: https://9to5google.com/2022/05/20/android-2022-distribution-...
Nearly a third of Android devices are on a version of Android >5 years old... just imagine if all your iOS apps had to target iOS 11 as a minimum feature set, and XCode defaulted to supporting iOS 8 for all new projects
When the apps can't rely on any newer features, it creates the illusion of backwards compatibility.
And the rest of your rant is about developers updating their app needing to track changes. That's an unrelated discussion. We're talking about backwards compatibility for apps that don't update. Meaning compile SDK & target API aren't changing. Android keeps those working quite well.
> So even design language changes can (and often do) break the UI.
Nonsense. The platform widgets are governed by the theme which almost never changes. Old apps that don't get updated will still be depending on Theme.Holo which is still there, still unchanging.
And most apps are primarily not using platform widgets anyway, they're using Jetpack instead. Things like RecyclerView, MotionLayout, ConstraintLayout, CardView, etc.. are not in the platform, they're in jetpack. Which is a static library bundled into the APK. And therefore obviously not changing with an OS update
> Android Studio defaults to targeting the latest API level
Whoops, you confused compileSdkVersion, targetSdkVersion, and minimumSdkVersion (I even mention targetSdkVersion separately as "compiled against")
You (wrongly) thought I was talking about targetSdkVersion (which often doesn't match compileSdkVersion on new releases because... targetSdkVersion lets you duck those breaking changes! That's why Google usually gives about a year before any given compileSdkVersion requirement [latest release] is graduated to a targetSdkVersion requirement).
I mean, read what I wrote again: "targeting a minimum SDK version of API 25".
Min SDK is still defaulted to selecting Lollipop in AS Dolphin which hit full release just this month, and when you ask AS for help it specifically highlights API 25. Try it yourself :)
-
> And the rest of your rant is about developers updating their app needing to track changes. That's an unrelated discussion. We're talking about backwards compatibility for apps that don't update. Meaning compile SDK & target API aren't changing. Android keeps those working quite well.
You didn't understand the conversation so you failed to follow the connection. I'm saying that Android doesn't do backwards compatibility well, but it doesn't need to since everyone is actively going out of their way to support old versions.
That's why any moderately long lived Android codebase will be full of:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.XXX) useOldPermission/Flag/Type else useNewPermission/Flag/Type
> Nonsense. The platform widgets are governed by the theme which almost never changes. Old apps that don't get updated will still be depending on Theme.Holo which is still there, still unchanging.
Forget OS version, the theme changes per device manufacturer! There've been cases of manufacturers redefining constants like android.R.color.black to be something completely different than black! That's why you can't rely on android.R for anything
> And most apps are primarily not using platform widgets anyway, they're using Jetpack instead. Things like RecyclerView, MotionLayout, ConstraintLayout, CardView, etc.. are not in the platform, they're in jetpack.
You failed to realize that the part of Jetpack they're using the most is a library literally called AppCompat. You know why it's called that?
It try (and sometimes fail) to wrap dozens of versions worth of incompatibilities, bugs, breaking changes, and missing implementations in the user space (app)!
It's a literal ode to my entire point, that Android *the OS* has never done backwards compatibility well, so developers *in userspace* end up putting a *ton* off work into glossing it over!
Imagine if on iOS you couldn't just make a UITextView, you had to use a wrapper around a UITextView because iOS 8 was still a valid target for many apps and any new feature for the UITextView in the OS had to be simultaneously back ported to iOS 8...
Just the other day I observed a case where the Jetpack Cardview worked on API 32 but broke on API 25 because on API 32 the library falls back to the built-in from the OS... Well it turns out the AppCompat implementation just randomly breaks if the radius of a corner is greater than View.height / 2. The OS implementation handles that gracefully.
That's why any half-serious development team ends up needing to run their apps on all those versions of Android (or just unwittingly lives the life of one of those randomly poorly behaving apps in the wild)
-
Like if you just slow your roll and read what I said, it shouldn't be controversial to any serious Android developer.
You said it yourself... Android has reached the point where basic UI development is literally built on a ball of strategies to work around the atrocious backwards compatibility situation via AppCompat and other libraries in Jetpack... do you realize that's not normal or indicative of an OS with good backwards compatibility? It's an utterly bizarre corner that Google backed themselves into and are aching for outs on
Which is not relevant to the discussion. The discussion is about apps that aren't updated. Android doesn't break those. Developers targeting previous releases is a wholly unrelated issue.
> AppCompat. You know why it's called that?
Because it provides compatibility for new APIs on older platforms. You seem to be completely lost on what backwards compatibile means.
It means old binaries/APIs work on new releases. Which it does on Android quite well. It does not mean that new APIs magically work on old releases. Which is the problem jetpack/appcompat is targeting, and is the entirety of your rant.
> android.R.color.black to be something completely different than black! That's why you can't rely on android.R for anything
And yet everyone does rely on android.R, because those color redefine issues are vanishingly rare.
There's also entire CTS suites that verify oems don't modify theme.holo and theme.material. which is why everyone inherits from those, and don't have problems with it
No, it is the discussion. If you rely on the OS and lean into new features, many updates will break your app, and in fact many devices on the same OS version will break it!
But there's a massive reluctance to rely on anything but the lowest common denominator of functionality in your apps, so there is outwardly an impression of backwards compatibility.
Seriously, you're talking about backwards compatibility when Android can barely do sideways compatibility, the mind boggles.
> And yet everyone does rely on android.R, because those color redefine issues are vanishingly rare.
Well I guess I'm referring to a certain level of experience... so just call it a code smell.
You get Lint warnings for not fully qualifying any use of it since it's usually not what you want.
Those of us who've needed to support enough apps realize it's really not that rare for random android.R overrides to exist in things like animations, and especially if you have a global footprint. So we just take 5 seconds to define ourpackage.R.color.black or ourpackage.R.anim.fade_in
> There's also entire CTS suites that verify oems don't modify theme.holo and theme.material. which is why everyone inherits from those, and don't have problems with it
No... they inherit from AppCompat wrappers on those because there are many subtle breaking changes between versions.
-
You're clearly not making the logical connection conveyed here, and I don't think there's anything wrong with accepting that.
No one will completely understand or agree with everything they read, but clearly others are able to make the link, and I think I've gone out of my way enough explaining the link, but you're completely stuck at the first step convinced that someone who's dealt with backwards compatibility for a very long time doesn't know what it is, instead of opening your mind to comprehending the bigger picture.
So I'll leave it at that :)
Most things that actually break on Android break for good reason, in my opinion. I consider giving apps the ability to draw overlays without any kind of permission in a supposedly sandboxed environment a design flaw, for example. I'm more annoyed by their restrictions on dynamic loading but even that still seems to work fine if you avoid the Play Store and set your API targets to a version that triggers the backwards compatibility system.
The recent change to the way uploading to Google Play works (where you have Google sign your apps instead doing it yourself) is the worst change in years, but that's technically a Google change, not an Android change.
Almost all API changes necessary to run old apps are minute. The permission overhaul for Android 6 (interactive permissions for many permissions that were previously granted install-time) requires a few more lines of code to show an error if the user denies a critical permission but it doesn't require a full rewrite.
The consequence is that app devs with some minimal time on their hands can update their apps to work on modern devices quite easily. Only apps that are thrown over the wall and abandoned or created by defunct companies are now broken.
Luckily, decompiling most Android apps is quite trivial. If the app is indeed completely defunct with the company disappearing, one might relatively safely maintain a decompiled fork of the abandonware to make it work on modern platforms.
It's a pain, but not a dissimilar amount of pain to searching working on NoCD cracks for games that require DRM broken on Windows 10. Enthusiasts do it, quite regularly as it turns out!
This is also why I'm in favour of laws about source control for abandonware; if a company doesn't exist anymore and people still use their software, the source code should be opened so customers aren't screwed over. Source escrow isn't unheard of in B2B applications and I don't see why it can't be done for consumer apps.
Also, right away any sort of law like that would become incredibly nuanced. I have a pacemaker and there's an optional BLE app for it. Security through obscurity is lame, but I'd rather that app's source code not be dumped on the internet if the pacemaker company stops supporting it. The source code wouldn't keep the app going because it is dependent on the cloud, and would only be of value to folk trying to reverse engineer the diagnostic protocol. Personally that sounds like a lot of fun, but it's also hardwired into my heart...
Source code for such products shouldn't be a problem because devices like these should definitely come with the necessary signature checks out of the box. Such key material shouldn't be released for anything important to one's health (medical devices, emergency devices, etc.). If you're at risk of having a heart attack when someone beats some kind of app code obfuscation then you're in for a bad time.
The cloud won't save you either. When the company disappears, their domain name expires eventually. Someone malicious could record and analyse API traffic and buy the domain to set up their own evil API server.
There are so many attack vectors for such a setup that I'm worried about how tech-ingrained such crucial devices are.
FWIW, Gentle Alarm doesn’t do that :D
It’s not quite clear why giving the permission helps, but without it, the alarm doesn’t go off when the screen is off (it still does if the screen is on and the app in the background).
I can easily see the dev calling into the API to initialise the alarm dialogue before actually playing the sound (after all, who wants an alarm they can't turn off?) and the API call that used to go through without issue now throwing an exception, killing the wakeup process dead in its tracks. I haven't reversed the APK, or course, but it's a very likely scenario.
I don't think this is how the API is intended to be used, but you can find plenty of stackoverflow answers like https://stackoverflow.com/questions/35327328/android-overlay... that (ab)use the window API. This one: https://stackoverflow.com/questions/46860993/window-over-oth... shows the API change, throwing exceptions on API level 26 (Android 8) that didn't get thrown before.
On modern devices, these old workarounds are usually no longer necessary. There's a separate API which is easier to use for interacting with the lock screen now and the permissions to take over the lock screen have been made harsher. For a maintained app this would mean fewer compatibility hacks, less weird lingering visual artifacts in edge cases and a better alarm. Sadly, with the dev ending their operation, the alarm is probably stuck calling old APIs with limited support now that Android security is tightening. Such a change broke clipboard sync in KDE Connect, for example, except it didn't leave a compatibility workaround for old apps.
I'm in favour of better privacy and security but restricting previously unrestricted APIs is a painful process. I've gone so far as to root my phone to provide the necessary permissions but I don't think I'll be able to do that forever...