Write programs for Android without writing apps


8 - 10 minutes to read, 1954 words
Categories: android
Keywords: POSIX android python scripting shell termux

I find writing an App for Android, compared to writing a program for a computer (Windows, GNU/Linux, …​), much more difficult.

Surely I did not fail enough times (lack of experience), but I think there is something that makes writing programs for Android fundamentally more difficult.

First; on a PC there is much more liberty on what language you can use.

Also, many programs do not need a graphical interface, as they simply need to show some textual data or take some textual input. On a PC it is not uncommon to write a program in a couple of lines of text, even if some people would not consider it a program.

On Android, every App needs to define a graphical interface.

Even writing a simple hello world is daunting.

First, one possibly needs to learn a new programming language (it is not possible to simply use C, C++, python, …​). Second, one needs to learn how to package and sign your App, define a manifest, permission, …​, and take care of dependencies. You cannot simply copy those on the target platform (which is a good thing in the long run, not so much at the beginning)

If something does not work as expected, you need to learn how to debug. This is not as simple as one might expect as it is generally not possible to run those programs directly on a PC (which I wonder why, as most programs are compiled to bytecode that is executed by a Java virtual machine…​).

Also, be sure to have a machine that is powerful enough! Android Studio requires at least 8GB of RAM and starting the Android emulator requires at least five minutes on my machine and feels terribly slow. Of course, you could use another IDE instead of Android studio. Considering that most (maybe even all) official tutorials use Android Studio and do not explain how to build a program by hand, but use the IDE to magically generate a lot of things, you better avoid taking that route, especially at the beginning.

And even when you have mastered all those things, writing simple programs is still much more complex compared to a two-liner…​

Making multiplatform programs is maybe harder than it should be, using libraries and frameworks for abstracting a lot of implementation details away has a cost too. This is not only theoretical, from a business perspective having only one codebase seems an obvious decision; some companies, like Dropbox used to have a shared codebase between Android and iOS.

POSIX

Probably the greatest idea behind POSIX was to define a good enough shell to make it easy to compose different programs together.

Many programs (and shells) developed on POSIX-like platforms have been ported to other operating systems; Windows and Android included.

Termux

Termux is a terminal emulator and Linux environment that runs on Android.

It is not available on Google Play Store since Android 10, as restrictions introduced in newer Android versions do not make it possible to download it from there.

On F-Droid it is still possible to download it, and currently, this is the only official channel for getting it, and where updates are published.

Termux widget is also a must-have when using Termux, as it makes it very practical to execute commonly used programs.

Some simple programs on my device

Those are some simple programs for which there definitively exists apps, but are much smaller, require much fewer resources (CPU, battery, disk space), and are generally easier to maintain.

dice

shortcuts/dice
#!/bin/bash

read -p "How many dices (default 1) " nr_dices;
read -p "Max value (default 6) " max_value;

nr_dices="${nr_dices:-1}";
max_value="${max_value:-6}";

for i in $(seq 1 $nr_dices); do :;
  echo $(($RANDOM % $max_value + 1));
done

printf 'Enter to close'; read -r ignore;

This program takes only 267 bytes, the code is easy to inspect and understand.

Compare it with easydice; the APK is 9MiB in size, a gigantic monster in comparison!

It is possible to create smaller programs, like diedroid. It is "only" 0.9Mib; the code required for making such a program is a lot compared to the bash script.

Depending on your use case, this bash script might not be enough. For example, the input of the user is not validated. Also using % is problematic, as the generated numbers are not uniformly distributed. Some values might have a higher chance to appear than others. Both apps do not have this issue, the input is validated and they use java.lang.Random.nextInt, which creates uniformly distributed numbers in a given interval.

The point still stands, writing a uniformly distributed dice in bash might be hard, but it is possible to use python, awk, C++ or any other programming language you like, and replace $RANDOM % $max_value + 1 with program $max_value, or even implement the queries in your new program and replace the script entirely.

speedtest

My current solution is to use speedtest-cli, as it is the same used in many GNU/Linux distributions.

I have a wrapper for the Termux widget, as I tested the connection periodically for a given period:

shortcuts/speedtest
#!/bin/sh

python3 ~/bin/speedtest-cli;

printf 'Enter to close'; read -r ignore;

Note that currently speedtest-cli requires 64K on disk. If the program wouldn’t be that lightweight, I would just store a bookmark to a webpage instead of installing a separate App, as an internet connection is required.

sshd

Instead of using adb, if possible, I prefer to use ssh for connecting to my Android device from my PC.

shortcuts/sshd
#!/bin/sh

termux-wake-lock
sshd

Optimize pictures

It is possible to optimize JPEG images to use less space without losing any quality. This is particularly useful when the disk is nearly full, or you want to share some images.

shortcuts/jpegoptim
#!/bin/sh

find ~/storage/dcim/ ~/storage/pictures/ \( -iname '*jpg' -or -iname "*jpeg" \) -type f -exec jpegoptim --preserve --strip-none --totals {} + ;

printf 'Enter to close'; read -r ignore;

This script is not particularly efficient, because it tries to optimize serially every time all images For my use-cases, it’s fast enough to get its job done.

It could be possible to store somehwere the information if a given image has already been optimized, and it is also possible to parallelize the optimization processes.

This shows how valuable it is to reuse existing programs; it makes it possible to reuse existing solutions without reinventing the wheel every time.

Query Reddit

A slightly more complex interaction between my scripts is parsing a specific subreddit for a given pattern (and acting accordingly). Reddit offers an API that serves JSON instead of HTML which, thanks to jq, is much easier to parse and transform.

shortcuts/query reddit
#!/bin/sh

/bin/sh ~/bin/query-reddit

printf 'Enter to close'; read -r ignore;
bin/query-reddit
#!/bin/sh

SUBREDDIT="...";
URL=$(printf 'https://www.reddit.com/r/%s.json?limit=100' "$SUBREDDIT");
TITLE_TO_MATCH="...";
JQPARAM=$(printf '[.data.children | .[] | {title: .data.title, status: .data.link_flair_css_class} | select(.title | contains("%s"))] | reverse' "$TITLE_TO_MATCH");
curl -s -A 'reddit scraper' $URL | jq "$JQPARAM"

The output is some pretty printed JSON, it might not be as user-friendly as a graphical application can be, but all I need to do is to copy some parts of the output, which is a two-click operation.

Backup

Termux offers also an API for reading SMS, which makes it possible to dump them and create an handy backups. With git/rsync/ssh and other programs it is easy to save all files automatically on another device, like a PC at home, when both are in the same network, without realying on external services. The best of it is that the tools I am currently using for backing up my computer are the same I’m using for Android.

Conclusion

Of course, I’m not counting the python and bash as dependencies when considering the complexity or size of a program, why should I?

I need to install those once and can use them multiple times for different tasks.

Android apps generally do not share libraries or other resources, which means they need more space both on the disk and in memory.

Also note that those programs can be executed and tested locally, on my PC, without any modifications or overhead. This has nothing to do with the fact that all examples are scripts, a C program can be compiled directly in Termux (it provides GCC) and on any Desktop system without modifications, as long as it does not use anything system-specific.

Most programs consist of 2 files; the program itself, saved in ~/bin or in some system directory, and a "launcher" in ~/.shortcuts.

The files that are not in ~/.shortcuts are responsible for doing the hard work, and generally do not interact with the user. This makes it simpler to reuse them in another context.

The scripts in ~/.shortcuts use whitespaces for separating words, as the script names appear in the Termux widget, and are thus more readable. They are also responsible for interacting with the user (querying values) and most important, thanks to printf 'Enter to close'; read -r ignore;, they avoid that the process finishes and the terminal window closes immediately.

No drawbacks?

On the contrary, there are drawbacks to using Termux.

Future of Termux

Since Android 12 there are further limitations that seem to break Termux.

There are workarounds, but it makes Termux harder to use, and seems to make the future of Termux uncertain.

Security model

Termux makes it easy to install and update programs, such as writing new ones, just like any GNU/Linux distribution or BSD system.

This breaks the security model of Android.

In Android, applications are isolated and can access only a subset of functionalities unless the end-user gives them the necessary permissions.

On Termux, all programs have the same permissions, unless special care is taken by the end-user.

In one of the examples, I’m using jq. How do I know that jq, or for what is worth even simpler programs like cat or cd, do not have a "backdoor" and access my contacts and send them together with other personal information online?

I do not know, just like I do not know on a regular computer.

With an android application, an end-user can be relatively sure if such things are not possible if a program does not have the necessary permissions. Of course, programs might exploit a vulnerability of the system, but that is another story.

Does it mean that one should not use Termux?

Just like every other application, one needs to trust the author(s) about what a program is doing.

In the case of Termux, there are a lot of functionalities packed together. The authors of Termux did not write all those programs from scratch, they rely on other existing programs that have been compiled for Termux.

Supposing that Termux itself is not malicious, the security model is the same as on a normal GNU/Linux distribution. As far as I know, repositories of GNU/Linux distributions, BSD systems and Termux, never contained malware.

Nevertheless, it is a possibility, just like it is for every distribution system.

Other distribution systems like pypi, npm, the Google Play Store and App Store had malware at least once.

Maybe there is not enough interest (not bigh enough user-base?), or maybe the fact that programs are compiled/packaged by the mantainers of the repository puts the bar on a much higher level.


Do you want to share your opinion? Or is there an error, some parts that are not clear enough?

You can contact me here.