Ask HN: Am I crazy or is Android development awful?
TL;DR - what I can do in 10 minutes on a desktop python app (windows or Linux, both worked fine) seems near impossible as an Android app.
I have a simple application to prototype: take a wired USB webcam, display it on the screen on a computer device (ideally a small device/screen), and draw a few GUI elements on top of it.
Using Python scripting and OpenCV, I had a working cross-compatible script in 10 minutes, for both Linux and Windows.
Then I realized I'd love this to work on an Android phone. I have devices with USB OTG, and a USB-C hub for the webcam. I confirmed the hardware setup working using someone else's closed source app.
However the development process has been awful. Android Studio has so much going on for a 'Hello World', and trying to integrate various USB webcam libraries has been impossible, even with AI assistants and Google guiding me. Things to do with Gradle versions or Kotlin versions being wrong between the libraries and my Android studio; my project not being able to include external repos via dependencies or toml files, etc.
In frustration I then tried a few python-to-android solutions, which promise to take a python script and make an APK. I tried: Kivy + python for android, and then Beeswax or Briefcase (may have butchered names slightly). Neither would build without extremely esoteric errors that neither me nor GPT had any chance to fix.
Well, looks like modern mobile phones are not a great hacker's playground, huh?
I guess I will go for a raspberry pi equivalent. In fact I already have tested my script on a RPi and it's just fine. But what a waste, needing to use a new computer module, screen display, and battery, when the smartphone has all 3 components nicely set up already in one sleek package.
Anyways that's my rant, wanted to get others' takes on Android (or smartphone in general) dev these days, or even some project advice in case anyone has done something similar connecting a wired webcam to a smartphone.
I've been developing Android since 2012. It was worse then. Still sucks now but isn't as bad. Esoteric errors are still the norm. With 10 years of experience you only have to swear a whole day when updating a library, instead of spending a week.
GPT does poorly with beginners - it's definitely something humans have advantage with AI and I expect the gap to get bigger.
I do not touch legacy projects anymore because they're always horribly broken, half the libraries no longer exist. Many of them are easier to rewrite than fix. You get weird bugs where A needs to be 1.71.0 but B needs A at 1.69.0 or 2+. Upgrading A to 2.0.1 will fix A and B but break CDEFG. Upgrading everything to max breaks switch-case, turns some of your brackets to lambdas, requires you to change your UI from XML to Kotlin, etc, etc.
If you want something to hack stuff with, I made this: https://github.com/smuzani/android-minimalist-template
Originally it was designed for AI with smaller context windows. But it works as a simplified version of our production codebase. The principle behind this is that you should have good peripheral vision and that the shape of the code resembles what it's trying to build.
Funny enough I actually did Android development contract work circa 2012-2014. I never did anything more complex than working with internal phone components (bluetooth, accelerometer/gyroscope, GUI/text, etc) and SQLite, but even so I quickly decided I wanted nothing to do with that platform.
Coming back a decade later for a side project, I guess I have the same opinion.
Now with the help of GPT-like assistants, I'm sure I could slog through some fairly vanilla development tasks like I did in the past, but when it comes to building anything a bit 'outside the box', no thanks.
Thankfully there are hardware equivalent packages (mini linux development machines like raspberry pi) that fit the bill, but they aren't as ubiquitous or nicely packaged as a modern smartphone unfortunately.
One wonders if there's some opportunity there, take all this great generic smartphone hardware (a $100 phone now is crazy) and package it with a developer-first OS. It could just be a linux system with a dumb, button-focused frontend for users to mimic Android/iOS.
I hit the same thing over a decade ago. Stick with Android and make a lot of money but hate life, or switch to something else and be happier.
> You get weird bugs where A needs to be 1.71.0 but B needs A at 1.69.0 or 2+. Upgrading A to 2.0.1 will fix A and B but break CDEFG.
Sounds like "modern" web development.
It would be interesting to see where this doesn't happen, you can't just update stuff without considering breaking changes and new bugs in new updates
Difference is that you only have to take your lunch break for it to happen in web dev. By the time you get back to work the following day the framework you're using is deprecated. At least with other platforms there tends to be a bit more stability.
Web libraries don't update more or less quickly than any other platform. The "issue" with web is the pace at which new frameworks are released but at this point even React is over ten years old. It's not that bad. Things are more stable than they used to be and new concepts are quickly adopted by each framework so you aren't forced to switch to something new, see for instance signals.
For someone who has never written an Android app before but knows Java, what's the "happy path" to getting a native MVP out the door in 2024? Must I learn Kotlin? Is there a "blessed API" or design pattern these days that's better supported than the others?
You don't have to learn Kotlin. It cut down LOC by about 40% by the time I picked it up, but today's Java has become more efficient and supports things like @nullable. Kotlin is nice though, and it leads into more advanced things like Jetpack Compose for UI and Kotlin Flow which is a nice way to do reactive programming.
Reactive programming is useful for front end because the UI will update as soon as the data downloads, so it scales linearly with complexity and API calls, instead of an exponential mess of if-else.
You can use the github repo I linked. I designed it to be complex enough to handle the harder tasks but simple enough for a beginner to reverse engineer. Just download, run to see it work, and hack it into what you need.
Thanks!
Hearing about this is very reminiscent of current day React web dev as well.
Oh, are GUIs not XML any more? Good. I am a programmer. Don't make me learn yet another language with no debugging tools. Just write the UI in the same language as the rest of my work.
(I look in on Android every few years, but I haven't done any real work in it.)
Haven't used XML for them in over 2 years (excluding replacing legacy code and fixing typos). They went deep into XML+data binding which people liked for a while, because you could do UI tests without building the whole UI and such. But it wasn't so good in production because building everything from XML was making build times long. So while you could test that it's outputting the correct UI content within 2 minutes instead of 12, it also meant assert(1+1==2) took 2 minutes too.
I believe deprecating kapt now also breaks data binding, though I don't know if it breaks all the other basic XML layout stuff.
Android is an example of technical debt from poor caked-in design. Its problems are still stemming from being rushed to market (relatively speaking) two decades ago. It's had enormous success as the most viable iOS alternative, but at a cost.
On the flip side, consider PalmOS. It was SotA at its debut in 1996. In the early aughts, Palm made Treo smartphones when almost no one knew what a smartphone was. It had a multiyear lead, yet it got easily marginalized by iOS and Android. Its technical debt was from maintaining backward compatibility with 90's apps, and cost it dearly. To be fair, company management sucked too.
The moral is: caked-in issues suck, but if you're going all in with a design, the most important thing is to time it with the explosion of the market. Palm was too early, others like Maemo and Windows Phone were too late.
Dart and Flutter were actually meant to be the better design. Lots of features from those were replicated on Kotlin-Jetpack, especially Compose. And lots of those features end up being copied to Java.
Dart-Flutter still supports them better natively though, instead of having to hack things like reactive programming via Kotlin Flow.
Flutter is at best no different IMO, as now not only do you have to deal with Flutter's build system for Dart, you also have to deal with Kotlin/the default Android build system when you want to do something not supported by the Flutter std libs, which last I tried was quite a lot. That was a few years back though so maybe its changed (though I doubt it). Jetpack Compose is similar in its "not much better"-ness to me.
I can't remember if it was Compose or Flutter, where I spent a ridiculous amount of time trying to get something to stay centered on the screen regardless of orientation. Something that I could do pretty easily and quickly with my own UI tech library in C++. However I can't use that code without having to jump through all the annoying hoops you have to jump through with JNI crap in order to use it. So I just don't bother with Android anymore.
Flutter is quite good now. Performance is actually better than SwiftUI out of the box and the ecosystem and tooling is mature.
Unfortunately with all the short-sighted cost cutting Google has been doing lately it's even harder to have faith that they won't axe it sometime soon.
Centering a widget regardless of orientation (and detecting the orientation) is incredibly trivial with Flutter. You might have just been tired at the end of a long day and missed something.
Yeah, my thought was it was someone unfamiliar with mobile measurements. It's meant to handle mobile UIs, which means "pixel" doesn't exist as measurement because screens are different densities, different aspect ratio. You could do a thing like make an empty block with full padding to the left or right, or just center align it.
I made a mobile game in Ren'Py and it was hard for me because of the fixed assumption that something was 800x600 and such and you'd add padding on the sides lol. Unfortunately with mobile, everything is relative to each other. iOS was a little easier back when it was one size, but now it's not.
It's still a lot easier to do than fixing sizes on CSS, flexbox, etc because you'd be able to have fine control over these things.
Now that I've thought about for a bit it was Compose I had that issue with.
I really just wish the Android group would get over their apparent disdain for native code and just let me write my app in C++ without having to deal with JNI BS.
Maemo was also too early I think. I guess the main problem was that the N800/N770 were not a smartphone, not mass-marketed and still too clunky for the general public (plus lack of unlimited mobile internet). Though the upgrade over PalmOS was impressive, went from barely able to load a modern web page to browing all the web smoothlessly while streaming online radios. (though this much shouldn't have been that impressive considering it's just basic multitasking and having enough RAM)
Ridiculously low-quality documentation, a build and development system that puts the local Rube Goldberg competition winner to shame, constant churn, total deafness or willful ignoring of wishes of dev ... and so on have nothing to do with what happened 20 years ago.
It's the classic "I would like to serve 5 terabytes"[0] Google problem.
(Their engineering culture reeks of this. See the tools they have released. Angular, Bazel, Go, Kubernetes, etc. The last one escaped the usual decline of incompetence because the community showed up.
Go has GOPATH. Even in a language designed for "simplicity" initially getting it set up had this roadblock.)
And no doubt the roots of the problem are manifold, but it seems all stemming from ongoing management incompetence (creation of shareholder value[1] maaaybe excluded, though I am very curious what kind of inane metrics the Android SDK team is whipped to chase).
[0] https://www.youtube.com/watch?v=3t6L-FlfeaI&t=0s
[1] https://www.wheresyoured.at/the-men-who-killed-google/
As primarily an end user of Android, it is fine. I like the more open nature of it.
But it is very clear that the guard rails were down especially for the first few years in trying to acquire functionality and market share by any means possible. Now Google is in space of trying to lock down the system while not breaking things.
macOS has decades-long technical debt as well (NSCell can still be found in the UIs you see), yet it remains incredibly robust aside from the years when Apple shake it with big visual updates.
It's incredibly robust compared to Windows
https://recorder.easeus.com/screen-recording-resource/macos-...
https://lifehacker.com/tech/mac-os-sonoma-update-fixes-scree... ... okay I don't even know what's this :D
Funny, for a lot of the functionality you get with Windows you have to pay some random dev for with MacOS. Window management alone feels like it's baby's first computer.
Last time I checked Windows still did not have anything like Quick Look, so for me it's the opposite. The only macOS enhancements I've been using since 2011 are Karabiner for keyboard customization and f.lux for warm colors at night.
of course, but that's on the feature completeness axis not on the stability (robustness), right?
I mean on macOS the Settings are so spartan it can really fit on an unfolded napkin. for power/battery management you need something like Amphetamine. Furthermore AFAIK there are no per-SSID network settings, so you either do DHCP or static IP. Have fun manually changing every time you go home-office. And so on.
What does caked-in mean?
https://dictionary.cambridge.org/dictionary/learner-english/...
> to be covered with a thick, dry layer of something
I read that, but it doesn't really make sense in context.
Sorry for the odd usage. The idea is taking a shortcut through a field and caking your boots in mud, or cheating in Game of Thrones and caking your sword in blood. I could have worded it better for sure.
FWIW, I think it was great (enough that it wouldn't hurt elaborating on the analogy when introducing it).
My mind went to machinery turning rigid and clunky over time due to being caked-in with a crust of thickening dust/rust/tech-debt, especially concentrated on sections "hot-fixed" with the metaphorical duct-tape/glue/lube/almost-fitting-spare.
If you want your machinery running smoothly and be easily servicable with off-the-shelf-parts, you can't skimp on maintenance for too long.
It's a typo. OP meant baked-in.
Yes, the Android SDK has to be one of the worst software packages to ever have been written. Just look at the sourcecode for TextView[0] if you want to see for yourself. 8,700 lines of code to show text on the screen? Well actually, TextView is actually a full blown text editor with the editing functionality turned off as a flag. EditText just wraps TextView and sets the `ediable` field to true. What genius software design! Ever wonder how those selection handles appear when you long press on text in a TextView? I wonder what component that is? Trick question – its built right in to TextView as well! It uses a popup window the displays the handles in global coordinates which it gets using a mixture of `getLocationInWindow` and `getLocationOnScreen`.[1] Another stroke of genius form the Android SDK! Want to change any of this functionality slightly? Now you have to make your own TextView starting from StaticLayout.
[0] https://android.googlesource.com/platform/frameworks/base/+/...
[1] https://cs.android.com/android/platform/superproject/main/+/...
Lmao, tbh all this is coming across as "Jr Engineer knows everything" syndrome.
The fact your [1] link is a class that's not even used in the TextView class isn't lost on me to start. They share an interface though, scary!1!!
The fact your [0] link is to a copy of the TextView from 2017 is even funnier.
> Just look at the sourcecode for TextView[0] if you want to see for yourself. 8,700 lines of code to show text on the screen? Well actually, TextView is actually a full blown text editor with the editing functionality turned off as a flag.
Hmm yes, 8,700 lines to "just show text". No hyperbole detected there. Who cares about fonts, shadows, or any other visuals on or around the text, all we're showing is "just text".
> Well actually, TextView is actually a full blown text editor with the editing functionality turned off as a flag.
And? It's called code de-duplication. While realistically I think the better approach would have been to have TextEdit be the barebones display only and Editor add the editing functionality, sometimes code is so tightly coupled for reasons that you can't do that easily. This approach is much better than hitting cmd+c/cmd+v and copying the code into a new class.
The funniest part to me is that your rant is about TextViews though. When that's been soft deprecated for 5 years already (replaced by Compose Text element).
>The fact your [1] link is a class that's not even used in the TextView class
The [1] link is only used by TextView. It is completely reliant on TextView and can't be used by other components. And yes, it is used, right here: https://android.googlesource.com/platform/frameworks/base/+/... mEditor is used over 400 times in TextView.java. Did you even read it before commenting?
>The fact your [0] link is to a copy of the TextView from 2017 is even funnier.
Why is that funny? Most of it has not changed. I linked to the up to date one in the second link. I searched "TextView source code" on Google to get the first one. It gets the point across and doesn't matter how old it is.
>Hmm yes, 8,700 lines to "just show text". No hyperbole detected there. Who cares about fonts, shadows, or any other visuals on or around the text, all we're showing is "just text".
I'm pretty sure a lot of that is handled by DynamicLayout, not TextView, although correct me if I'm wrong here. If if it isn't, it should be, and is indicative of poor software design. Shadows certainly should not be handled by TextView, I have no idea why anyone would think that.
Take a look at Flutter's implementation. Text is just 1,400 lines, a large portion of which is documentation (another thing the Adnroid SDK sorely lacks,) and it just shows text to the user.[0] Somehow all the "tight coupling" issues have gone away here, and there is no need to throw a text editor into the code. How does Flutter edit text? It has a base EditableText class[1] that is then exposed by simpler widgets like TextField[2]. Now if I want to make my own custom editable text I can without having to recreate the whole thing.
>And? It's called code de-duplication
No. You don't get rid of separation of concerns to save a few bytes. If TextView cannot be made into a separate component that EditText uses then it should implement the functionality of TextView on its own. This is called the single-responsibility principle. A TextView should not be a texteditor. It can't get any simpler than that. Either refactor the text viewing components into something that can be shared by TextView and EditText, or separate them completely.
>The funniest part to me is that your rant is about TextViews though. When that's been soft deprecated for 5 years already (replaced by Compose Text element).
I wonder why this great piece of code was deprecated if it's so great? And yes, that's another great thing about the Andorid SDK. Everything is deprecated while its replacements are only supported on new devices. Then you end up having to do:
if(onReallyOldDevice){
}else if (onOldDevice){ }else{ }See eg. accessing file systems.
[0] https://github.com/flutter/flutter/blob/master/packages/flut...
[1] https://github.com/flutter/flutter/blob/master/packages/flut...
[2] https://github.com/flutter/flutter/blob/master/packages/flut...
> I wonder why this great piece of code was deprecated if it's so great? And yes, that's another great thing about the Andorid SDK. Everything is deprecated while its replacements are only supported on new devices.
Again, same vibes.
The reason you are seeing anything like this, is because you are looking at foundation code and expecting app code. This code is going to be used by apps to run on ALL devices. Best way I can try to describe it is just library code sits between the kernel and software, it has to support everything. Company X's latest XR/AI app doesn't.
Software is constantly evolving for whatever the latest trend is be it VR, AI, or whatever, and eventually you move on from devices that don't get updated. But, so do users. Users by and far want the latest and greatest, shiniest thing. That means every company wants to support `thing`, even if it means dropping `oldThing`.
Funnily enough I had to have a discussion at my job today about dropping support for FireOS 6 devices because of OS specific bugs that happen with Compose that cause a buggy UI. We can't make it work exactly as we want while providing a good experience, so we won't be providing an experience at all. The reason that's okay? Those devices have usage percentage that's practically nil, as they are older devices and not the "latest and greatest".
>Again, same vibes.
Are you serious? The Android devs have been working to fix the deprecation and update issue for the last decade and a half. I think you are actually the junior dev here if you are defending it. They have been slowly moving from their custom fork of Linux back to mainline, separating device-level components (eg. Bluetooth) as separate modules, trying to force device vendors to support a baseline of features via GKI, trying to separate kernel updates from higher level system updates, and trying to increase SoC support duration from vendors like Qualcomm. The minuscule device support length on Android is a real issue that Google has spent tens of millions of dollars trying to fix (and only now are they even close to being able to start fixing it). A lot of it is due to political decisions that began at the beginning of Android's lifetime, when device vendors had much more control over the operating system. The fact that pointing that out as a flaw gives you "junior programmer vibes" is seriously concerning.
Also, you failed to address even a single point I made in my post about TextView.
> The fact that pointing that out as a flaw gives you "junior programmer vibes" is seriously concerning.
It's the fact that you hand wave away Text rendering as "just showing text" while claiming you've made your own.
Then claim that platform code is terrible because it...uses flags to determine what platform it's on and use the appropriate commands...
THAT is what gives me JR eng vibes.
> Also, you failed to address even a single point I made in my post about TextView.
And there's the lack of reading comprehension with a Jr.
"You didn't say anything about X component."
Yeah, when talking about components A-Z and the structure around them you don't typically need to point out that X will be included, but here we are.
>It's the fact that you hand wave away Text rendering as "just showing text" while claiming you've made your own.
I didn't wave away "text rendering" at all. TextView as nothing to do with text rendering. Have you tried reading the code? Also, even if it did, that would not make it any better. Your claim that TextView is good code because it implements everything from text layout and rendering to text editing is actually much much worse that it simply doing what it really does, which you would know if you would just read and understand the code. Why you have not done so by now is puzzling. Think of it this way: if you were looking at the source code of a text editor, would you expect the whole program to consist of just two classes? That is always going to be bad code.
>Then claim that platform code is terrible because it...uses flags to determine what platform it's on and use the appropriate commands...
Windows has backward compatibility going multiple decades. It even used to ship with a DOS emulator to ensure you can run programs from 30 years ago on it. Linux too has never broken ABI compatibility (although the same cannot be said for user space). Yet you seem to think it is fine for Android to break its API every update. Have you developed for any other systems? I get the feeling that all you know is Android and its awful SDK so you feel you have to defend it.
>Yeah, when talking about components A-Z and the structure around them you don't typically need to point out that X will be included, but here we are.
No. There were two points I made in the post you responded to. One was a very specific point about TextView where I gave my arguments as why it is bad code and in which I pointed out that you never even read the code we were talking about. The other was a side point about deprecating APIs in Android. You decided to ignore the entire main points of my post and only respond to the side point.
"to just show text" is such a tell that you know nothing about UI. Displaying text is extremely complex. This is only 8000 lines because skiaa does the brunt of the job. Also, who gives a shit about TextView? Just use BasicText, we aren't in 2017 anymore.
The actual layout algorithm is handled by DynamicLayout, not the textView. It really is just supposed to show some text. You can see it here.[0] Almost all the difficult aspects of showing the text, such as alignment, text direction, line spacing, line breaking, ect. as well as the actual rendering of the text are handled by StaticLayout/DynamicLayout. All TextView should be doing is basically just allowing you to add text programmatically and handling the selection handles. That should not entail having a text editor.
>"to just show text" is such a tell that you know nothing about UI
I have actually made my own TextView using just layout so I don't think this comment is warranted.
[0] https://cs.android.com/android/platform/superproject/main/+/...
> I have actually made my own TextView using just layout so I don't think this comment is warranted.
Make sure you handle the following attributes and how they affect each other!
> text, bufferType, hint, textColor, textColorHighlight, textColorHint, textAppearance, textColorLink, textFontWeight, textSize, textScaleX, fontFamily, typeface, textStyle, cursorVisible, maxLines, maxHeight, lines, height, minLines, minHeight, maxEms, maxWidth, ems, width, minEms, minWidth, gravity, scrollHorizontally, password, singleLine, selectAllOnFocus, includeFontPadding, maxLength, shadowColor, shadowDx, shadowDy, shadowRadius, autoLink, linksClickable, numeric, digits, phoneNumber, inputMethod, capitalize, autoText, editable, freezesText, ellipsize, drawableTop, drawableBottom, drawableRight, drawableLeft, drawableStart, drawableEnd, drawablePadding, drawableTint, drawableTintMode, lineSpacingExtra, lineSpacingMultiplier, justificationMode, marqueeRepeatLimit, inputType, imeOptions, privateImeOptions, imeActionLabel, imeActionId, editorExtras, elegantTextHeight, fallbackLineSpacing, letterSpacing, fontFeatureSettings, fontVariationSettings, breakStrategy, hyphenationFrequency, lineBreakStyle, lineBreakWordStyle, autoSizeTextType, autoSizeMinTextSize, autoSizeMaxTextSize, autoSizeStepGranularity, autoSizePresetSizes, textCursorDrawable, textSelectHandle, textSelectHandleLeft, textSelectHandleRight, allowUndo, enabled
>textSelectHandleLeft, textSelectHandleRight
Done
>textColor, typeface, textColorLink, textFontWeight, textStyle
handled by TextPaint in StaticLayout/DynamicLayout. For example textColorLink is just `linkColor` from TextPaint.[0]
>text, textSize, maxLines, justificationMode, breakStrategy, hyphenationFrequency, lineBreakStyle
handled by StaticLayout/DynamicLayout
>shadowColor, shadowDx, shadowDy, shadowRadius
mTextPaint.setShadowLayer(radius, dx, dy, color);
Wow, that was so difficult. Only those that "know about UI" must be capable of such a feat?
>numeric, digits, phoneNumber, inputMethod, editable, cursorVisible, textCursorDrawable, allowUndo, inputType, imeOptions, privateImeOptions, imeActionLabel, imeActionId, editorExtras,
Only needed if you add a text editor into your text view, which I did not do.
I'm not going to go through all of these because I'm not sure exactly which side implements them (for example elegantTextHeight sound like something TextView does, but I'm not sure.) I suggest you actually sit down to read TextView before you make comments about it.
[0] https://developer.android.com/reference/android/text/TextPai...
> Only needed if you add a text editor into your text view, which I did not do.
> I'm not going to go through all of these because I'm not sure exactly which side implements them (for example elegantTextHeight sound like something TextView does, but I'm not sure.) I suggest you actually sit down to read TextView before you make comments about it.
Which is exactly my damn point, you expect your case to be the only one used. They have to think about EVERYONE and their use cases and how everything interacts.
Have you handled LTR text correctly, custom unicode in fonts, weird alignment issues due to accent marks?
My guess would be no, simply because you never thought of them.
>you expect your case to be the only one used
I expect the text editor to be a different component. Take a look at any other UI toolkit's text view like Swift for example:
>A view that displays one or more lines of read-only text.[0]
or QT:
>QLabel is used for displaying text or an image. No user interaction functionality is provided.[1]
In fact, even for just displaying text, I still expect rich text to be handled by a separate component. In Flutter you have RichText for example.[2] I don't know why are are confusing separating components with the components existing at all. Yes, "just displaying text" should be a simple component, because any reasonable UI toolkit will have already abstracted out all the layout code into a level bellow the user facing widgets, and the simple text component will just call into that.
>Have you handled LTR text correctly
That is handled by Layout via setTextDirection, not TextView. This is what I meant by saying you should read the code. Also I already mentioned text direction in my previous comment in this chain which I see you have not bothered to read.
>custom unicode in fonts, weird alignment issues due to accent marks?
Huh? Just read the code. TextView is not doing any of that.
>My guess would be no
All you have to do si wire up these fields from the XML input (another awful ASDK technology). That's really what TextView is meant to do: send its values to the underlying Layout and handle text selection like copy-paste. I didn't want to wire up XML that I don't need so I didn't. None of it is particularly hard.
[0] https://developer.apple.com/documentation/swiftui/text
[1] https://doc.qt.io/qt-6/qlabel.html#details
[2] https://api.flutter.dev/flutter/widgets/RichText-class.html
Getting native libraries to work well on Android is a beast. I happened to have done exactly what you're describing though, specifically rendering libusb through an Android phone. My code is at https://github.com/kevmo314/kineticstreamer and you might be particularly interested in the CMake build at https://github.com/kevmo314/kineticstreamer/blob/main/app/sr...
Happy to answer any questions or help you out if you decide to keep going down this road, shoot me an email at kevmo314@gmail.com. Ultimately an Android phone is still just a Linux computer but jumping through the hoops is definitely hard.
Hey thanks for this! I gave it a try, imported and built in my Android Studio ("Koala" if that matters), tried getting it installed on a phone, and unfortunately got this cryptic error:
> ninja: error: 'lib/libjpeg.so', needed by 'C:/Users/ADMIN/AndroidStudioProjects/kineticstreamer/app/build/intermediates/cxx/Debug/3xf5p505/obj/arm64-v8a/libkinetic.so', missing and no known rule to make it
That being said, I browsed through the code some more and while I think it's a great Android project, I don't think (assuming I got it working) it would be advisable for me to build on top of this. The existing complexity, and my lack of faith on cross-compatibility (different phones, SDK updates, etc) are a turn off. Heck I've even seen certain libraries and includes fail because they require different versions of Java/JDK that I have available.
So in summary, I think the solution for myself at least for now, will be to explore a different hardware route. A cheap raspberry pi equivalent, with a small display, and battery - annoying to have all these extra components but at least I know it'll work reliably.
>got this cryptic error:
> 'lib/libjpeg.so' missing
whats cryptic about that?
I get the sense that the only development environment the OP knows at all is Python. With that perspective I understand why they might think that error is cryptic.
People keeps forgetting that pretty much everything is C-based and only a few language ecosystems have abstracted it away enough. And even then, if you want to program in slightly esoteric environment, you have to confront that fact. Just understanding how C/C++ projects are used (libraries, header file, linking,...) can get you really far if you have to stray from the happy path.
Don't forget Android 15 changes pagesize from 4K to 16K, and you have to recompile those ...
https://developer.android.com/about/versions/15/behavior-cha...
It's not that awful once you get hang of it, but it's a mess made by google. Kotlin which is maintained Jetbrain is catching up. Google is far less interested in owning kotlin. Therefore creating a confusion with mix of grovy, maven, java and xml as hell.
I also agree that the development experience is awful. I have more than 10 years as an Android developer and Android Studio (someone remember when it was derived from Eclipse?) is painfully slow, even in modern machines. Just starting a new project is a ridiculously sluggish process. Also Gradle is a piece of hyper-complicated software that (almost) nobody is interested in, but it is there and you have to deal with it. Nowadays I am basically moving to Flutter, much more simpler and easier than kotlin.
Most of my stack overflow points are from helping people run their build in Eclipse :)
Gradle is deprecated now though. And Jetpack Compose is about as convenient as Flutter.
Gradle replaced Maven which replaced ant which replaced make. The tech treadmill was one of the reasons I retired early and I'm glad I did.
What is the new hotness replacing Gradle?
Kotlin DSL
https://developer.android.com/build/migrate-to-kotlin-dsl
This one makes sense, though the improvement is minor.
That's still Gradle. Just a different language to configure it.
Yep. And I still use Makefiles to this day.
Eh, thanks for the correction. I originally read it as Groovy. Unfortunately, I can't edit or delete my original comment, but feel free to downvote it.
Gradle replacing maven seems like a stretch. Maybe on Android. But everywhere else Maven is still going strong.
I'd like to know where that is because I've watched as a lot of major 3rd-party Java libraries switch to Gradle from Maven.
This is an Android thread. In this context, Gradle has most definitely replaced Maven.
I don't think that's the context when they referred to ant and make.
Gradle is the single worst thing about Android development imo. It's an obtuse, un-debuggable mess.
Library management got a LOT nicer when it was introduced, but surely we didn't need all of that to achieve it.
Personally I use Bazel, but I was at Google for a decade and so I miss Blaze. Of course that has it's own steep cost the first time you use it because of ideological differences between repos inside Google and repos outside Google.
At this point I have a clean repo with Blaze set up that I use as a starting point for Android applications. Then Android Studio with the Blaze plugin and I'm set.
I remember asking some Android devs, "How do I install a compiler on Android?"
They proceeded to tell me what to download on my laptop. I repeated my question, emphasizing "ON Android". They gave me blank looks. I said, "I want to install a toolchain ON an Android device, and run it there. How do I do that?"
They had no idea.
I asked, "What if you want to compile something that requires compiling something, then using that something further down the line, like Perl?"
Again, no idea.
A platform without a native toolchain is a very awkward place to be. I stopped trying to wrap my head around it and stopped playing with Android.
To me it just sounds like you want Termux. It works pretty well for things like gcc, Python, or Perl.
For fun, I managed to get a full X environment running, including Intellij! The amazing thing was that it actually ran fairly decently on a Pixel 5, though it did tend to run out of memory with anything more than trivial projects.
This looks like exactly what I wanted to find! Thank you.
I had been soured by the Android platform because I bought a brand new device, mostly because it had a physical keyboard, only to find out that it wouldn't get any new updates, nor could I use Skype on it, nor could I tether with it. Android was supposed to be the "open" platform, but at the time (which, admittedly, was something like ten or so years ago), it wasn't.
If I can use Termux to get a modern OpenSSH on to my device, it may get used yet! Thank you :)
You can indeed use SSH. As client OR server.
"Toybox's main goal is to make Android self-hosting by improving Android's command line utilities so it can build an installable Android Open Source Project image entirely from source under a stock Android system. After a talk at the 2013 Embedded Linux Conference explaining this plan, Google merged toybox into AOSP and began shipping toybox in Android Marshmallow in 2015." --Rob Landley
http://landley.net/toybox/
Sounds like an X Y problem.
What you want is to cross compile using the NDK toolchain. That should get you 95% of the way there (barring tweaking with downstream project flags to work with bionic libc and limited Android user land and other Android idiosyncrasies)
What I really want (or wanted, I should say) is a native toolchain that runs on the Android device, not a cross toolchain that runs elsewhere. NDK isn't that.
/? termux USB webcam: https://www.google.com/search?q=termux+usb+webcam
Termux was F-droid only, but 4 years later is back on the Play Store: https://github.com/termux-play-store#current-status-for-user...
Termux has both glibc and musl libc. Android has bionic libc.
One time I got JupyterLab to run on Android in termux with `proot` and pip. And then the mobile UI needed work in a WebView app or just a browser tab t. Maybe things would port back from Colab to JupyterLab.
conda-forge and Linux arm64 packages don't work on arm64 Android devices, so the only option is to install the *-dev dependencies and wait for compilation to finish on the Android device.
Waydroid is one way to work with Android APKs in a guest container on a Linux host.
That Android Studio doesn't work on Android or ChromiumOS without containers (that students can't have either).
When you get x on turmux working you see what mobile development could have been and weep for the fallen world we live in.
containers/podman > [Feature]: Android support: https://github.com/containers/podman/discussions/17717 :
> There are docker and containerd in termux-packages. https://github.com/termux/termux-packages/tree/master/root-p...
But Android 13+ supports rootless pKVM VMs, which podman-machine should be able to run containers in; (but only APK-installed binaries are blessed with the necessary extended filesystem attributes to exec on Android 4.4+ with SELinux in enforcing mode.)
- Android pKVM: https://source.android.com/docs/core/virtualization/architec... :
> qemu + pKVM + podman-machine:
> The protected kernel-based virtual machine (pKVM) is built upon the Linux KVM hypervisor, which has been extended with the ability to restrict access to the payloads running in guest virtual machines marked ‘protected’ at the time of creation.
> KVM/arm64 supports different execution modes depending on the availability of certain CPU features, namely, the Virtualization Host Extensions (VHE) (ARMv8.1 and later).
- "Android 13 virtualization lets [Pixel >= 6] run Windows 11, Linux distributions" (2022) https://news.ycombinator.com/item?id=30328692
It's faster to keep a minimal container hosting VM updated.
So, podman-machine for Android in Termux might help solve for development UX on Android (and e.g. Android Studio on Android).
podman-machine: https://docs.podman.io/en/latest/markdown/podman-machine.1.h...
Wait so you're telling me I can run podman on android?
Looks like it's almost possible to run podman-machine on Android; and it's already possible to manually create your qcow for the qemu on Android and then run containers in that VM: https://github.com/cyberkernelofficial/docker-in-termux
Android development is Kotlin. Sometimes C++, but I've never seen or worked on a project that needed it. Using any other language will be an uphill battle that will make your life harder.
OpenCV also has a warning and a guide for people trying to use it for Android dev https://opencv.org/android/. Did you look through this?
Also why do you want to use a USB camera when every phone has a couple cameras built in? I think you're going down a road of frustration if you think mobile OSes aren't built with completely different use cases in mind than desktop environments.
Theres a lot of information the Android dev site about getting up and running with the camera. You can pass a lot of the photo stuff off to other camera apps on your phone, but if you really need to do stuff in the app theres an official Android library for making your life easier. Theres also a lot of official Android libraries and well known libraries for images and videos that might be easier to work with than OpenCV. You don't actually say what you are trying to ultimately do.
Gradle is the part of Android dev everyone hates.
I think you're just going through the learning curve of something new. You could make the same argument about a React/Next app being unnecessarily complicated with Hello World.
I loathe to say this, because I still have a soft spot for the language, but you could say the same thing about Python development in 2024
> Do you want to break your Linux installation or rearchitecure your runtime? [Y]
(But really, Android dev is a qualitatively different level of fucked up compared to React or any major Python framework I can think of. React Native, though...)
As someone who moved from pure iOS development to cross-platform iOS+Android development in C# with native UIs – big nope! Android development is a mess, it takes at least twice as long to build exactly the same UIs as on iOS, and there are endless edge cases between versions and also hostile API, such as not allowing a developer to know when a software keyboard appears/disappears. It was especially frustrating at the start, but has not become much easier with experience.
Android development is definitely insane. Just the process for getting a dev environment setup is stupidly complicated compared to almost anything else.
So… similar to setting up a dev environment at most FAANGs? ;)
Android Studio isn't that bad, but their design system is horrible. After years dealing with that crap I ended creating my own WebView wrapper and moved all the design and logic to HTML5, which I write by hand, never been a fan of frameworks. Even created a WASM obfuscator with Python, and my apps autoupdate without relying on Google Play, by dowloading a compressed package. Whenever these are taken down I just set a flag/link in the DB and the app will instruct the user to get the re-published app.
Sadly the golden age of the app store is long gone. I used to make thousands monthly around 2015 with silly apps, but all went down the drain by 2018. Making apps isn't worth anymore.
I've found React Native, especially in recent times, to provide a very good mobile dev environment.
I wrote an app and had it running in both iOS and Android in no time (with minimal iOS dev and zero Android xp prior to that).
My app included the Jitsi video extension (with very customized Jitsi controls and self-hosted backend), so not just a simple CRUD app.
(To be fair, my background is mostly Node and React, but those skills made it a breeze.)
or capacitorjs
"PilBox (`PicoLisp Box') is a generic Android App which allows to write Apps in pure PicoLisp, without touching Java, and without the need of an Android SDK.
"You do not need to root your device. And - if you prefer - you do not need a separate development machine (PC or laptop): All can be done in a terminal on the device, and even in a Lisp REPL while the App is running."
https://picolisp.com/wiki/?pilbox
"Using Python scripting and OpenCV, I had a working cross-compatible script in 10 minutes, for both Linux and Windows."
What took you 10 minutes would take me a long time to learn. I rather enjoyed making some basic Android apps. I didn't work with much hardware stuff and heard that part is tough due to all the variations.
Appreciate the ego boost, but it was literally some modifications to python opencv demos available on their webpage. But that's what's amazing, it was up and running so fast and worked cross-platform after 5 minutes of debugging something with ChatGPT.
Yes it's become quite clear to me that using an Android phone is not a good development platform to work with external hardware devices. I understand this has never been it's intended purpose, but come on, we have a linux kernel sitting under the hood. Just feels like a waste of potential.
Why use external hardware when they have cameras built in? I'm sure you could find an example or open source app that uses the camera and just modify that, like you did with the openCV.
“even with AI assistants and Google guiding me” seems like part of the problem, because you’re missing the higher-level knowledge that Android, like all mobile operating systems, is a sandboxed environment where the supported runtimes evolved to facilitate low level hardware access and provide an “easy” GUI and touch development model, not a low-level one.
So you either reimpmentent the whole thing in a native way (using Java/Kotlin or C++ for lower level integration) or you’re SOL. You can embed Python libraries, but you’re better off learning to use wherever native analogues and frameworks the platform already support.
I personally stay the heck away from Android Studio (I got a very early start in Android development, so most of my projects are just Gradle/pom.xml or a Makefile atop a “normal” Java tree).
That said, you have _a lot more flexibilty_ in incorporating multiple languages and non-native frameworks than, say, in iOS.
It is pathetic. I have been an Android developer for more than a decade and some aspects of it have become shittier. One of the other, seems tangential problems, in Android development world is architecture fatigue. Every other week the cool kids will change to something else and everything else becomes "so old school". For what? No one knows. It's just because the upstream (i.e. famous) cool kids are doing that. One blog post or even tweet by them and your junior teammates indignantly start demanding we must rewrite the whole codebase to the new holy tunes. Then there are libraries. In a way that is great that we have so many libs especially compared to iOS dev world. But then even small tasks means someone just added a library and you have a hard time explaining that just because there is a library doesn't mean you should add it without thinking of the implications and maybe not at all add it if all you have to do add a bit of code on your own for a tiny task.
If you ever have to work with native code (or things like OpenCV) start praying from day one and never stop.
You need bigger and bigger laptops to even run that disgrace of an IDE Android Studio. This always gets me!
So dev tools/env? Oh, god! Fuck Google!
Coming from iOS development, it was incredibly frustrating not to have an event for software keyboard appearance/disappearance. I tried researching the issue and ended up in Google Groups, where an official Google representative was smugly telling the developers that they did not need such a feature to make Android apps.
Ah, those Google Groups where you are made to feel like an idiot for just reporting an issue and then few centuries later someone with some @google.com email comes and says something completely unrelated and closes it.
You are just trying to do something that nobody cares about making work on smartphones, and so you are "on your own".
Trying to do userland USB in an Android app to talk to a UVC webcam connected through USB OTG is not something even a niche of apps care for, and the native camera framework definitely doesn't care about because if it was trying to workaround the UVC spec Android phone cameras would have never left the original Gameboy camera age.
So with no native support for your use case, you are now having to wrangle the pretty shitty libusb and the even more terrible libuvc in working within the confines of an Android app. And to the credit of Android, this is possible! People have made it work! People with in depth knowledge of how the parts fit together, that is, and so GPT won't be of any help.
I'm not a professional Android developer, but a few years ago I did create and publish a small app to the Play Store (and discovered that there's whole new category of spammers promising to make my tiny app become #1!).
Android development is not simple. Take time to learn the architecture and underlying concepts. It took me a couple of weeks and some false starts to make sense of things (although back then I was a college student; a professional can probably get started faster).
Android is a commercial modern platform, where developing MUST BE HARD to discourage most and makes the few who can rule the others, meaning the big ones. Windows is similar but being much older and born without the iron under control underneath it's much less, *nix systems tend to be open.
You are not crazy and the pain you feel is the pain of commercial IT. Not strictly need to commerce of course, but that's the modern common practice. The cure is FLOSS, mandatory, from the start.
Take it from someone who has worked on android dev tools - yes.
Not only is Android a mess but the Google Play Store is terrible too. There's now this insane requirement that devs have to find 20 testers on their own for two weeks before publishing anything and, incredibly, the Play Store review process is also qualitatively slower and worse than Apple's.
I think we're going to see the tendency accelerate to develop and validate ideas on iOS first and only later outsource a crappy Android port.
What do you mean “going to see”? It’s been that way for over a decade, albeit with some ebb and flow.
Going to see accelerate.
External play stores can't come too soon.
> I have devices with USB OTG, and a USB-C hub for the webcam.
Using an external webcam with an Android device seems a fairly exotic scenario doesn't it? Whatever, I would intuitively expect (disclaimer: almost no experience in mobile development) the Android OS to detect a USB-attached camera as another built-in camera and expose it via common APIs rather than let you access it via some sort of low-level libs reading the USB.
Started Android development back in 2011, Android SDK was just a plugin for Eclipse back then. It's way better now compared to before. Does anyone remember Ant, it was way worse.
But I feel you, if you don't have enough experience dealing with different Android, Gradle, AS errors then you're really having a bad day. But shouldn't be a deal breaker, just give it some time and more familiarity.
Piggy backing this topic. I started android developmentin 2011, did about 7 years of it. I took a contract job in a different technology.
I want to jump back to Android dev contracting, my two questions for the up-to-date Android devs: - Do you have any resource to catch up with what I missed in the past 4-5 years of Android development? - How is the Android job market these days, compared to the iOS one?
-
Yes it is. Use Ionic/Capacitor to create an app in Angular/React/Vue like you would on web with html and Javascript, Capacitor then embeds the webview into a native app
You won't have to touch any horrible Kotlin nor Swift but still be able to publish the app on the stores if you want to.
Android app development is awful but compiling native binaries/libraries is not that bad ime. Super easy in Rust.
The project directory structure of Android/Kotlin apps, at least as generated by Android Studio, is indeed offputting. I look at the rust and python programs I have for PC, embedded, and web, and can confirm that the android layout is more complicated than is required in those three domains
It's not you, it is bad. It has been getting better. Developing with Jetpack Compose is a nearly a clone of the experience of building with SwiftUI in Xcode. Android Studio and the emulators are resource pigs still.
Related from just over a month ago:
Why is Android Development so difficult/complex? (compared to Web and Desktop)
https://news.ycombinator.com/item?id=40742719
There's a bigger issue here: OP describes writing prototype software on a desktop, and compares this to writing more production-style software on a highly constrained mobile device. This isn't an apples-to-apples comparison.
Python packaging is notoriously bad, and while you can get a Linux/Windows compatible script without too much work, getting to a single executable that just runs is much harder. Cloning a repo, setting up a virtualenv, installing an openssl dependendcy or whatever, is just not something that exists in the mobile world. We have to put more effort into the packaging, and that means a higher bar for things like this. There are answers to this in Python that claim to produce single, relocatable, Python binaries, and I've never seen one without a huge list of caveats. Even yesterday I was patching an open source library that didn't work inside one of these because it had the gaul to use... checks notes, os.path.
> Well, looks like modern mobile phones are not a great hacker's playground, huh?
This sums it up. They are not. The security environment on these devices pretty much ends this before you even get to writing any code, and that's generally a good thing. Phones are appliances for most people. There's a reason why "apps" took off in a way that boxed desktop software never did, and there's a reason why boxed desktop software on Windows did far better than package managers on Linux. Almost everyone wants more a more polished experience. Shipping a Python script running OpenCV to a phone is not going to produce a polished experience.
amazingly, the browser has pretty much solved all of this. fully compatible EMCAscript implementations on every single device with hardware access (such as the camera, as is needed in this post)
I don't buy your "security through difficulty" argument for that reason alone.
I don't really mean "security through difficulty", I mean that on phones we have sandboxing, permissions, and a bunch of other factors that make phones much more secure than the average desktop/laptop. Browsers do provide a pretty good option here, but that comes at the cost of the browsers themselves being highly complex, and privileged software on the devices.
OP writing this prototype as a web app would likely have been the path of least resistance to having something work on mobile.
I'd argue they were trying to do prototype software for Android as well, and that's not a thing you can do. Which is the problem...
Android devs, are there any good places online where experienced and friendly devs answer questions? (I need some handholding and the advice I got from Reddit usually turned out not quite right.)
Strong agree - it's horrible. I can't get past the enormous amount of boilerplate code that's required to do anything - even the proverbial Hello World.
> Using Python scripting and OpenCV, I had a working cross-compatible script in 10 minutes, for both Linux and Windows.
Which toolkit did you use?
Android development is pretty bad
but I never had trouble loading in C/C++ libraries with the NDK beyond the debugging issues
I enjoyed building Android apps using flutter framework but never touched the native though
Mobile is evil. Mobile is false dharma. That's why all the $$$'s in it.
Android is a piece of sh.. from developer perspective (and arguably from a user one).
Known fact, take it or leave it :)
To be fair UI development can not be simple in itself.
Because of the exponentially growing state machine => simple Rails style general purpose frameworks are impossible, it will always be a challenging problem.
Android is crazy bloated, leaved it completely & never look back.
Kotlin is a dream. I literally love writing it.
Back when I was in undergrad, I recall how I was taught C. Just read one of the bible books on a weekend, and was ready to go. I was recently taking a look at Kotlin books and literally banged my head on the table. I realized the language has a good rap but it is ridiculously feature-laden .. to the point they threw in the kitchen sink. A key positive of languages is easiness to learn. I really wonder about Kotlin. It may be well-designed, but did it really need to be so big?
I'm also curious if it is just me. I am a grey hair now, with many other responsibilities. Why were C, Python and Go so easy for me when kotlin seems so hard to penetrate (for me)? Is there a way to quantify language complexity?
Not an apples-to-apples comparison.
Take the K&R C book. It describes the language itself only - not the standard library. The Kotlin docs describe the language _plus_ parts of the Kotlin standard library which is why it appears to have lots of features. You'd have to read through half the standard C library documentation & pthreads docs in addition to K&R C to get the equivalent experience.
I will also say: Android Kotlin and pure server Kotlin are entirely different beasts. If you are on Android and you are frustrated with Kotlin, it is probably Android.
Kotlin compiles now to JS, WASM... even LLVM bitcode if you want it to. Coming to Kotlin from a pure lang perspective, I'm not sure what it would be like, it might not be you. I know as someone who came to it through Java that it is a massive improvement on what I had before.
What do you mean "so big?" Kotlin doesn't feel "big" to me.
`
enum class Sample { A, B }
val x: Sample = Sample.A
val y = when (x) {
}`
I think if you give it time you might like it. It takes some getting used to, sure, but especially compared with the alternatives (Java to use JVM, Java on Android, etc) it's pretty great.
Cross-platform Kotlin is very new but it works surprisingly well.
I found Kotlin easy to pick up, and use, but there are always complicated parts of it I haven't yet grokked. I'm sure a working knowledge of it is easy to obtain but I'm with you on the more dense pieces.
Kotlin + Jetpack Compose is my absolute favourite way to build apps.
Jetpack Compose feels underrated around here. It basically has most of the upsides of React, but with far fewer downsides. If it weren't for the fact that it's basically Android-only[0], I would probably stick to Kotlin for all my side projects.
[0] I know there's Compose Multiplatform, but I don't trust cross-platform compilation to be reliable.
Can't imagine who would downvote this comment as I'm definitely not claiming that _you_ need to like Kotlin, or that _your_ language is bad. I just like Kotlin. Sorry! :)
Try using Expo! I've found it to be much easier than native development on either platform, and its fairly easy to move through if you know web stuff.
If you think Android app development is crazy, try to work on Android itself.
> Well, looks like modern mobile phones are not a great hacker's playground, huh?
I'm using a GNU/Linux phone and I'm super happy with how playgroundish it can get if I want.
That would be my ideal device haha... have any particular devices of that nature you'd recommend? Lower end on cost would be preferred.
I've been using a Librem 5 as my daily driver for years now. I also have a PinePhone, but it's quite slow compared to L5.
Phones are optimized to handle RF. My engineering advice is to build your application with that in mind.
A wireless webcam is the simplest thing that might work. Hosting a video stream on other hardware might be the second simplest thing.
Good luck.
Except, phones have exceptional cameras. You'd be spending just as much on a dedicated camera
I remember reading “wired USB webcam” in the question, but maybe I misunderstood.
You should try iOS dev.
It's amazing Apple hasn't fixed the bug where switching branches will break an Xcode build.
https://stackoverflow.com/questions/78244976/package-resolve...
That is definitely an issue but it's easily worked around. You just have to close Xcode before switching branches.
It's much, much better. I'm doing both and it always takes at least 2x time to do the same thing on Android. Apple's API are much more consistent and the overall architecture of UIKit is just great (thank to its AppKit ancestor).
The feedback we get is SwiftUI is half-baked while the newer Android stuff is a lot more stable.
OTOH, Apple does a better job at handling things like languages, currencies, and all those experience, whereas Google is notoriously unreliable despite all the best practices. It's common practice to just "force" the wrong locale on an app to handle translations because a user's device would be English-US and yet someone wants the display in another language. OR someone wants a certain local currency in the form of 1.000,00 and not 1,000.00 (which also wreaks havoc with BigDecimal etc) and yet they'll keep the language and formatting as English and you'd have to do some override. We spent weeks on things like this and the iOS solution would just be "use device settings lol"
That’s like saying “may you live in interesting times.”
Sounds fun at first, but it always ends in tears.
Where does that quote come from? I have been saying it for years but I have lost the source!
It’s an apocryphal Chinese curse: https://en.m.wikipedia.org/wiki/May_you_live_in_interesting_...
The phrase "may you live in interesting times" is the lowest in a trilogy of Chinese curses that continue "may you come to the attention of those in authority" and finish with "may the gods give you everything you ask for." I have no idea about its authenticity.
I read it first in the "Interesting Times" by Terry Pratchett. I don't know did he invented this phrase or borrowed it somewhere.
welcome to real software development
Agrred.Android Studio Takes too much time to start