-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
54bbab4
commit af33ce6
Showing
1 changed file
with
233 additions
and
0 deletions.
There are no files selected for viewing
233 changes: 233 additions & 0 deletions
233
blog/posts/2024-05-15-Minimalist-mobile-app-development.html.draft
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
<p> | ||
I decided to make a mobile app for a project, and was interested in the | ||
options out there for cross-platform development. In particular, I'm | ||
interested in minimizing the effort required to maintain it over time and | ||
maximizing the amount of code that can be reused across Android, iOS, web, | ||
and native solutions. | ||
</p> | ||
|
||
<p> | ||
For some background, I was a core engineer working in Amazon and AWS's | ||
Builder Tools organization, and helped define and maintain the underlying | ||
build infrastructure for projects like Amazon's retail shopping app, its | ||
Kindle app, and its Twitch app. Mobile development has not been a career | ||
focus of mine, but my work in infrastructure and Amazon's software ecosystem | ||
has facilitated faster iteration for apps that you may use in your day-to-day | ||
life. I've even spoken at internal conferences in Amazon specifically to | ||
demonstrate how to build mobile applications (the Amazon way). In other | ||
words, I've got more than a passing acquaintance. | ||
</p> | ||
|
||
<h2>First, some rejects</h2> | ||
|
||
<p> | ||
My goals may not be your goals, so don't take these suggestions as gospel. | ||
I don't have unlimited time or an unlimited budget for engineering talent, | ||
I am limiting my investment to just my own spare time. I'm also not doing | ||
anything that needs fast-rendering pixel-perfect graphics (Maybe then I'd use | ||
<a href='https://love2d.com'>LÖVE</a>). | ||
</p> | ||
|
||
<p> | ||
Flutter is an attractive option. I love the Dart programming language and it | ||
comes with a large community that's reaching maturity. It also comes with a | ||
large package ecosystem with ready-to-go integrations for fiddly things like | ||
accepting in-app payments or integrating with advertisers. Those are not | ||
clear goals of mine though. | ||
</p> | ||
|
||
<p> | ||
Generating a simple "hello world" Flutter app instantly filled me with dread, | ||
though. Gradle files, Xcode projects, CMakeLists.txt, and multiple | ||
sub-projects for each target. This instantly put Flutter out of reach for me | ||
and my smaller-scale ambitions. Each of those build systems to me represent a | ||
tower of dependencies and moving parts to keep updated over time, and much of | ||
the platform-specific code appears non-trivial. I'm not opposed to the | ||
systems (at least, not for the right price), but it's going way over my | ||
budget for time and effort, especially over time. | ||
</p> | ||
|
||
<p> | ||
React Native is another attractive option, but again, my tolerance for <a | ||
href='https://npmgraph.js.org/?q=react-native%2C+react-native-web'>a large | ||
tower of dependencies</a> is low. If possible, I only want to have a handful | ||
of reasons to require updates. Changes to the OS or the store are impossible | ||
to avoid, but changes to (at the time of writing) 536 dependencies are | ||
certainly possible to avoid. | ||
</p> | ||
|
||
<p> | ||
Other options like Xamarin, Iconic, or Electron are either delivering too few | ||
platforms or too many dependencies for my goals. Perhaps in a few years I'll | ||
choose <a href='https://tauri.app'>Tauri</a>, but it's not ready for mobile | ||
yet. | ||
</p> | ||
|
||
<h2>Fyne, I'll do it already</h2> | ||
|
||
<p> | ||
I've settled on <a href='https://fyne.io'>Fyne</a> as a framework I can work | ||
with. I don't know what the possible lower bounds on minimalism can be in | ||
the cross-platform world, but it comes with <a href='https://github.com/fyne-io/fyne/blob/d8e9fe02c9bb9e4b4c42778f5cae8ffcc43f36e2/go.mod'> | ||
an order of magnitude fewer dependencies</a> than React Native. In going | ||
through a similar "hello world" app, it becomes clear that the amount of code | ||
reuse between platforms will be very high. There is no extra build | ||
boilerplate like Gradle/Xcode/CMakeLists.txt to maintain. (Again, my goals | ||
may not be your goals, some projects will require the level of detail and | ||
optimization that can only be achieved with complex build procedures.) | ||
As a bonus, the Go programming language has a fantastic track record of | ||
backwards compatibility with previous versions of Go. | ||
</p> | ||
|
||
<h2>Minimalist Android Setup</h2> | ||
|
||
<p> | ||
The rest of this article will be notes on my development setup. As a warning, | ||
I prefer to work very minimally and to stick with text interfaces (CLIs, etc) | ||
that lend to automation, and I tend to prefer avoiding GUI-based interactions | ||
for software development whenever possible. If you're more of a GUI person, I | ||
recommend following Fyne's <a href='https://docs.fyne.io/started/'>Getting | ||
Started</a> guide. | ||
</p> | ||
|
||
<h3>1. Dev environment</h3> | ||
|
||
<p> | ||
First I setup a fresh Ubuntu machine specifically for app development. You | ||
don't <em>have to</em> do this separation, but with all the fiddliness I've | ||
experienced with Android in particular, I want to constrain resources (like | ||
disk usage) and avoid interfering unexpectedly with my primary system. I | ||
primarily use Void Linux, but there's a little better support for Android | ||
specifically from Ubuntu. | ||
</p> | ||
|
||
<p> | ||
Originally I was working with Ubuntu in a QEMU VM on a local network host, | ||
and was able to get as far as emulation and successfully uploading an APK to | ||
a physical android phone. The phone was connected to my laptop via USB, and | ||
my laptop connected to the VM over Wi-Fi from a different room while watching | ||
a toddler. It's 2024 and it feels like almost anything is possible. The lag | ||
on input was bothering me, though, so I changed to Ubuntu on a cheap mini PC | ||
running XRDP for a remote connection and it's a lot snappier. I'm not really | ||
breaking the bank, just a small machine with about 8GB RAM and lotsa storage. | ||
</p> | ||
|
||
<h3>2. Dev dependencies</h3> | ||
|
||
<p> | ||
Next I setup the system with Go, GCC, graphics headers, and Go libraries. The | ||
initiated are going to understand this means | ||
<a href='https://pkg.go.dev/cmd/cgo'>Cgo</a> is in the mix somewhere, and | ||
we're not dealing with "pure" Go. Personally I understand this as necessary | ||
when developing cross-platform, although I imagine it will change in the next | ||
5 to 10 years. | ||
</p> | ||
|
||
<p> | ||
Nothing too fancy here for Fyne, I followed the steps from | ||
<a href='https://docs.fyne.io/started/#prerequisites'>the getting started guide</a>. | ||
</p> | ||
|
||
<p> | ||
I also installed a text editor (helix), an IDE (VS Code), and the Go language | ||
server (gopls). I'll use GitHub for controlling revisions of my software over | ||
time, so some setup in GitHub and on the machine for git was also performed. | ||
How you'll edit code will come down to some personal choices and go beyond | ||
the scope of this post. | ||
</p> | ||
|
||
<p> | ||
A Java Runtime Environment (JRE) will be required for many of the Android | ||
tooling, so I also installed the most recent LTS version of Java using | ||
OpenJDK 21's JRE. On Ubuntu, I installed the <code>openjdk-21-jre</code> | ||
package with <code>apt</code>. I'll only be using Java for android dev tools | ||
and not for compilation or at runtime, so I don't feel the need to get fancy | ||
with Temurin or Corretto or some other hardened distribution, or to worry | ||
about Java build tools like Gradle/Maven/Bld. | ||
</p> | ||
|
||
<h3>3. Android dependencies</h3> | ||
|
||
<p> | ||
Here's where I will diverge from the crowd a bit. I start by installing | ||
<a href='https://developer.android.com/studio#command-line-tools-only'> | ||
command line tools</a> only. This download requires a license agreement, | ||
which is a recurring theme with all android tooling, so I did this through a | ||
browser to my <code>~/Downloads</code> directory. | ||
</p> | ||
|
||
<pre> | ||
cd "$HOME/Downloads" | ||
unzip commandlinetools-linux-*.zip | ||
./cmdline-tools/bin/sdkmanager --sdk_root="$HOME/android" --install 'cmdline-tools;latest' | ||
</pre> | ||
|
||
<p> | ||
Next, I add create an <code>ANDROID_HOME</code> environment variable, and add | ||
some android binary directories to my shell's <code>PATH</code>. This will | ||
vary by shell, but will look something like this: | ||
</p> | ||
|
||
<pre> | ||
# Bash | ||
echo 'export ANDROID_HOME="$HOME/android"' >>~/.bashrc | ||
echo 'export PATH="$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH"' >>~/.bashrc | ||
|
||
# Zsh | ||
echo 'export ANDROID_HOME="$HOME/android"' >>~/.zshrc | ||
echo 'export PATH="$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH"' >>~/.zshrc | ||
|
||
# Fish | ||
set -U ANDROID_HOME "$HOME/android" | ||
set -U fish_user_paths "$ANDROID_HOME/cmdline-tools/latest/bin" "$ANDROID_HOME/platform-tools" $fish_user_paths | ||
</pre> | ||
|
||
<p> | ||
Now source the new settings or restart your shell session as necessary. | ||
</p> | ||
|
||
<p> | ||
This gets far enough to use <code>sdkmanager</code> to start installing the | ||
other required Android dependencies, and accepting yet more licenses. | ||
</p> | ||
|
||
<pre> | ||
sdkmanager --install ndk-bundle | ||
sdkmanager --install platform-tools | ||
</pre> | ||
|
||
<p> | ||
And, believe it or not that's enough to... | ||
</p> | ||
|
||
<h3>4. Get started building an Android app</h3> | ||
|
||
<pre> | ||
fyne package -os android -appID my.group.MyApp -icon icon.png | ||
</pre> | ||
|
||
<p> | ||
That creates an APK, which is the minimal runnable application for Android. | ||
To actually run the APK on an android device, you can attach one via USB to | ||
your development machine. The device needs to <a href='https://developer.android.com/studio/debug/dev-options'> | ||
allow developer options</a> to upload directly from USB, and we can use | ||
<code>adb</code> (Android Debug Bridge) from Android's <code>platform-tools</code> | ||
package to upload the file. | ||
</p> | ||
|
||
<pre> | ||
adb attach | ||
adb install my_app.apk | ||
</pre> | ||
|
||
<h3>5. Packaging the Android app for distribution in the Play store</h3> | ||
|
||
<p> | ||
Coming soon | ||
</p> | ||
|
||
<h2>Minimalist iOS Setup</h2> | ||
|
||
<p> | ||
Coming soon | ||
</p> |