9 ms·
I just commented on the reddit post about this but I'll bring it in here too: The app implementation is out of touch with modern Google Play privacy requiremen
by crowbahr 4y ago
I just commented on the reddit post about this but I'll bring it in here too:
The app implementation is out of touch with modern Google Play privacy requirements and APIs.
I read through his code, starting with the Main Activity: https://github.com/M66B/FairEmail/blob/master/app/src/main/java/eu/faircode/email/ActivityMain.java https://github.com/M66B/FairEmail/blob/master/app/src/main/j...
1. He's using ancient APIs. All written in Java with Activities instead of Kotlin with a single Activity and many Fragments. There are some fragments but it's definitely an old writing style
2. He's using Tasks for multithreading/event handling
3. Using Handlers & runnables is a terrible idea and intrinsically fragile
4. The way he's handling synchro (persistent foreground service) is _explicitly something Google is targeting for battery issues_
5. This code is entirely unmaintainable. He's got a 3k line service file here: https://github.com/M66B/FairEmail/blob/maser/app/src/main/java/eu/faircode/email/ServiceSynchronize.java https://github.com/M66B/FairEmail/blob/maser/app/src/main/ja..., nested deeply with multiple different handlers running.
I'm not even going to discuss the fact that he has Logging statements peppered throughout the code etc.
This app looks like a 5+ year old code base, not something persistently maintained.
He also does not appear to use any modern Android APIs that Google requires, despite declaring the following restricted permissions:
1. READ_CONTACTS
2. READ_EXTERNAL_STORAGE
In fact I see him explicitly calling deprecated methods that Google has declared off limits: Line 474 of https://github.com/M66B/FairEmail/blob/master/app/src/main/java/eu/faircode/email/FragmentSetup.java https://github.com/M66B/FairEmail/blob/master/app/src/main/j... `requestPermissions` is an illegal call, which he has documented as throwing an exception that he can't figure out.
That's absolutely a smoking gun and potentially the reason Google would ban him. ActivityResultLauncher is required for permissions grants.
My summary of this is: This is what bitrot looks like and what happens when you don't manage app scope to handle tech debt. It got too big to maintain.
- alaricus 4y agoI call bullshit on this. Google should not get to decide this. As I consumer I want this app.
- crowbahr 4y agoThen build & side load it. The issue is that he's not respecting the required APIs. It literally does not function on a modern Android device because of the permissions. Do you want privacy on your phone? Apps are required to implement the new API for better user control of privacy and permissions. The developer was incapable of maintaining their app to modern API changes. That sucks but it's like complaining that you can't run a Windows 95 program on Win 7 without having to do some work on it yourself.
- alaricus 4y agoThe stuff about APIs is nonsense. The app works fine. It's better and more secure that Google's own email client. The problem is Google has no place making these decisions. This is textbook anticompetitive behaviour. The developer is based in EU so I hope (and expect) that google gets a hefty fine. And yes, I will be sideloading it.
- crowbahr 4y agoGreat. When you update to Android 11 or 12 it will cease to work well, because it will crash when requesting a permission. You can get around it by manually adding permissions. When you encounter those issues I suggest forking it and doing the work he refuses to: Use ActivityResultLauncher with registerForActivityResult to request permissions.
- rjzzleep 4y agoI'm sad to see it go as well. It's my main mail client on Android. The GP on this thread is completely ridiculous. "You're not using Kotlin and instead use Java" is the most ridiculous thing on such an issue I've ever seen. Email clients battery usage is a really hard to get right. Especially since Fairmail gives you so many options on the synching behavior. So much so that a lot of iOS email clients actually store mail credentials on a third party server and sync your emails there to send push notifications. That's an absolutely security nightmare and yet that's somehow ok. Really sucks to have it pulled and even more disturbing to see people here justify it. I can't help but wonder if the person above is a google employee.
- YPPH 4y agoThank goodness Google is looking out for my privacy! It's doing about as good of a job at that as it is in upholding my right to decide what apps to run on my device. It's remarkable that all that so-called "unmaintainable code" results in an app which is far more powerful, and just as reliable, as Gmail.
- Cthulhu_ 4y agoI dread to think what gmail's codebase looks like, I've heard Stories. Some resources: https://www.quora.com/What-was-the-code-quality-of-the-initial-version-of-Google https://www.quora.com/What-was-the-code-quality-of-the-initi... https://news.ycombinator.com/item?id=2452126 https://news.ycombinator.com/item?id=2452126
- crowbahr 4y ago1. The issue here is one of failing to maintain the code, so I don't see how calling it unmaintainable is unfair 2. Google is absolutely doing a lot to prevent 3rd parties from reading your contacts and sending them to a 3rd party server (like this developer was doing). I'm not saying your data is private, I'm saying you have more control over data privacy... but probably not from Google. 3. You can still run this app on your device. Android Studio is free. Go fork, build & side-load it. It will however crash on later versions of Android. Manually giving it permissions should resolve that through at least Android 13. We'll see what 14 brings.
- bhcompy 4y ago> You can still run this app on your device. For now. Google's in the process of killing the ability to sideload apks
- dzikimarian 4y ago1. How is he failing to maintain it? There was no single issue with code quality in this situation. 2. He is not sending contact list anywhere. If application finds john@gmail.com in your contact list, it makes request for https://gmail.com/favicon.ico https://gmail.com/favicon.ico it's off by default, and has disclaimer next to it. It poses literally zero privacy risk. 3. I use this app daily on Android 12, and this is last android version available for regular users. There's zero issues with it. I would be very happy if all apps were maintained up to this level. I couldn't care less about java being used in order to make that happen.
- andreasley 4y agoThanks for actually taking a look. I can imagine that the developer would have been more willing to make changes if Google had sent him the list you have compiled here.
- fourthark 4y agoI don't see what is wrong with an app being 5 years old. That's not very old in the scale of things!
- Aachen 4y agoI'm not an android dev, can someone weigh in here? Why is using Tasks bad? Who really cares if he uses a design pattern from five years ago? I'm sure my website code is at least twice as old and PHP, should I spend time rewriting that in Kotlin, too? > The way he's handling synchro (persistent foreground service) is _explicitly something Google is targeting for battery issues_ My phone has a terrible battery that will drain in 3 hours while navigating¹, but FairEmail running in the background is not noticeable. I've used K9 before as well and didn't notice any difference in battery use. ¹ worst battery I ever had in a phone, and also the most expensive phone I ever had... thankfully I got it second-hand and didn't pay the full price for this. Got a second one for my mom which was equally bad, so we had her device's battery replaced by samsung for iirc €110, but her battery longevity barely improved. Coincidentally I ruled out an hour ago that it's the screen that causes the drain, my next best guess is the CPU. Not sure why this model is such a battery hog, but anyway FairEmail doesn't impact it. > This app looks like a 5+ year old code base, not something persistently maintained. FairEmail was the only app that would receive updates every time the f-droid repository had a new release. Most apps go months between updates but of FairMail there were updates almost daily. And it's just this guy working on it all the time, I don't know where he got the energy. So maybe not the "maintenance" shiny new code patterns you'd like to see, but the maintenance I was very happy about was a constant stream of updates.
- sdflhasjd 4y agoThe comments on code quality are somewhat fair, and there are better ways of doing things, but calling it "out of touch" because it's not been rewritten in kotlin is frankly silly. Additionally, None of this is justification for removal from the store, the comment calling `requestPermissions` illegal is unjust, there's nothing incorrect about its use here (notwithstanding Play Store policies around contacts). ActivityResultLauncher is a more modern (imo superior) and recommended, but it is not a requirement. God forbid we have some tolerance for developers who don't want to spend every waking moment rewriting their app to use whatever new API Google have just added...
- crowbahr 4y agoIt's illegal because it crashes the app on the latest versions of Android. It's an illegal operation, not "against the law in N countries" type of illegal, more the "Divide by 0" type of illegal. The out of touch is my personal assessment of reading through the code: They doesn't seem to recognize the benefits of the modern Android code styles which would reduce their workload, decrease the boilerplate they're writing, and increase the stability of the app overall.
- chimprich 4y ago> He's using ancient APIs. All written in Java with Activities instead of Kotlin with a single Activity and many Fragments. That doesn't mean it's ancient at all. Java isn't deprecated, and using Fragments instead of Activities is just one possible architectural approach. I think Google recommends Kotlin now, but that's only been the case for a couple of years or so. Google's constant demands for changes to how Android apps are configured are very annoying to the developer, but even they're not that bad.
- crowbahr 4y agoA lot of my analysis is personal and subjective based on 5yoe as a full time Android Dev. The ancient APIs is using Runnables/Handlers with Tasks more than it is using Java. The single (or reduced) Activities with many fragments will improve stability. Kotlin has been the official language of Android for a relatively short period of time, true, but it's entirely interoperable with all Java code, and improves maintainability _significantly_. The main issue he's facing here is your last sentence: He refused to change how the app was configured. Use of illegal calls (which he helpfully posts the Stack Trace as a comment when it fails) means the app just doesn't work on modern Android without having to manually grant permissions.
- na85 4y ago>Kotlin has been the official language of Android for a relatively short period of time, true, but it's entirely interoperable with all Java code, and improves maintainability _significantly_. Has the JavaScript culture of rewriting everything every two years purely for the sake of change infected android now too?
- bhcompy 4y agoIt's been that way since at least Android 9
- formerkrogemp 4y agoYes, we all exist on treadmills and race the Red Queen nowadays.
- g_p 4y agoOne thing I've noticed about FairEmail is that it is able to do low power push messages via IMAP IDLE, without any kind of external cloud push platform, and maintain this reliably across connectivity state changes. Indeed, with a good mail server, it often seems more reliable than Gmail and their own push implementation. I don't know enough about the design patterns expected of an android app, but I think there's something to be said for getting robust functionality on as many versions of android as possible (including older devices), and in then keeping that sync engine stable once it works. Given the amount of per device bugs you encounter, moving to newer APIs is likely to result in a whole host of new regression issues that users won't like.
- bhcompy 4y ago> it often seems more reliable than Gmail and their own push implementation. Definitely is. Gmail doesn't set priority on email, so it gets stuck behind Doze, particularly on devices with more aggressive power management features(Samsung, OnePlus, etc). FairEmail is the most reliable email client I've found on the platform
- saagarjha 4y agoHaving a bunch of legacy code isn’t really a valid reason to block an app from being on the Play Store. Your code review isn’t particularly useful here. It might be if you went “oh this permissions API is not supposed to be used and you can see Google asked the app to use the new API to be approved” but that’s not what seems to have happened here?
- Avamander 4y agoMost of what you listed is either incorrect, irrelevant or purely subjective. I'm doubting your familiarity with the system. > All written in Java with Activities instead of Kotlin ... > The way he's handling synchro (persistent foreground service) is _explicitly something Google is targeting for battery issues_ Yes and Android will kill the app if it violates a constraint. It's not forbidden or won't get your app rejected. > He also does not appear to use any modern Android APIs that Google requires, despite declaring the following restricted permissions AAAAA. The use of those permissions is not forbidden, they're even needed for backwards compatibility. On newer Android versions and newer target API level, you probably have to start using the new APIs, but that's normal. This won't get even your app rejected. (Contacts is not special even in that aspect, you just have to have a good reason to use that) > In fact I see him explicitly calling deprecated methods that Google has declared off limits Deprecation doesn't mean absolutely forbidden. At worst it means that code won't work on newer Android versions and will throw an exception, won't get you rejected. > That's absolutely a smoking gun and potentially the reason Google would ban him. Absolutely none of those things is a sufficient reason for a ban. At worst a rejection might happen for other reasons stemming from legacy code, but I don't even that applies here. Keeping up with the churn of Android takes work and is difficult for most, but legacy code won't get you a ban like this. The reason is something else.
- crowbahr 4y agoThe ban is more explicitly stated in a different comment as having scraped & sent emails to a 3rd party server. Also he targets API 32 so the app will crash if he's not using the right API.
- aceazzameen 4y agoAre we playing a game of telephone by adding extra "facts?" "scraped and sent emails to a 3rd party server" is grossly exaggerating other comments which was also ended up being wrong in their assessment.
- dingleberry420 4y ago> All written in Java with Activities instead of Kotlin > The app implementation is out of touch with modern Google Play privacy requirements and APIs. Kotlin is never required. I think you might be the one of touch.
- _emacsomancer_ 4y ago> 1. He's using ancient APIs Maybe I don't fully grok how APIs are evaluated here, but FairEmail seems to be on API 32 (Android 12L), which is the very latest