Android Apps and System Configuration Notes

Overview

This document contains my personal notes about how to setup my Android phone. It is mostly kept as a lightweight alternative to proper configuration management since I would expect that to be a PITA to setup on Android and overall probably not rewarding for a single device.

It also turns out that the apps to install and use are highly Android-version specific, hence this list explicitly mentions different sets of Apps that I installed on different Android versions.

My Android App List

Apps in parentheses were not installed on the most recent version.

Android 2.3.X (Samsung Galaxy XCOVER)

Android 7 (Blackview)

Android 11 (Gigsaset GS5 Lite)

App Name Store
Maxima Keyboard apkpure.com
Maxima on Android apkpure.com (v3.2.1)
Morse Code Agent apkpure.com (v2.2.0)
GPS Test apkpure.com (v1.6.3)
GPS Test f-droid.org
Hacker’s Keyboard f-droid.org
NetGuard f-droid.org
OSMAnd~ f-droid.org
QR & Barcode Scanner x2 f-dorid.org
Termux f-droid.org
Termux:API f-droid.org
TI 84+ Emulator f-droid.org + separate ROM
Stashcat/Hermine apkfun.com (Build 5409302)
Daydream Digital Clock ? forgot where it’s from ?

Using the Phone as a Backup Server

By installing the correct apps and configuration, the phone can serve as a simple backup server. For my purposes, the backup server has two functions:

  1. Contain a separate copy of the backup from my main machine.
  2. Upload this backup to a remote location while idle. Specifically, Mega https://mega.nz is selected as the “remote location”

To achieve such a setup with Android, it is most useful ot rely on Termux for receiving the data (through rsync and ssh) and for uploading them to Mega (through rclone). This avoids less stable syncing that is being criticised about the Android Mega App.

Important General Config

To ensure that this works at all, Termux has to run sufficiently continuously. While one can achieve this with a permanent “wakelock”, this drains batteries too quickly.

A more battery-saving choice is to enable the Screensaver aka. Daydream such that while charging, the phone stays on. This way, while charging, Termux stays active and data can be processed.

Termux Configuration

To perform the initial setup, the following commands are used in Termux:

pkg install vim openssh htop bmon nmap tmux wget iproute2 netcat-openbsd rsync rclone
termux-setup-storage
cp .../authorized_keys .ssh
chmod 600 ~/.ssh/authorized_keys

Connection through SSH is then possible for the follow-up configuration.

echo "set-window-option -g mode-keys vi" > ~/.tmux.conf
df -h

This identifies the SD card as /storage/2FD8-1F16

mkdir -p /storage/2FD8-1F16/masysma/termux
cp .../ma_termux_server.sh /storage/2FD8-1F16/masysma/termux/ma_termux_server.sh

RClone configuration for Mega

% rclone config
2022/10/17 15:58:44 NOTICE: Config file "/data/data/com.termux/files/home/.config/rclone/rclone.conf" not found - using defaults
No remotes found, make a new one?
n) New remote
s) Set configuration password
q) Quit config
n/s/q> n

Enter name for new remote.
name> mega

Option Storage.
Type of storage to configure.
Choose a number from below, or type in your own value.
[...]
30 / Mega
   \ (mega)
[...]
Storage> 30

Option user.
User name.
Enter a value.
user> email

Option pass.
Password.
Choose an alternative below.
y) Yes, type in my own password
g) Generate random password
y/g> y
Enter the password:
password:
Confirm the password:
password:

Edit advanced config?
y) Yes
n) No (default)
y/n> n

Configuration complete.
Options:
- type: mega
- user: email
- pass: *** ENCRYPTED ***
Keep this "mega" remote?
y) Yes this is OK (default)
e) Edit this remote
d) Delete this remote
y/e/d> y

Current remotes:

Name                 Type
====                 ====
mega                 mega

e) Edit existing remote
n) New remote
d) Delete remote
r) Rename remote
c) Copy remote
s) Set configuration password
q) Quit config
e/n/d/r/c/s/q> q

Termux Autorun

One important thing to make this server run in battery-preserving manner is to only start it while the phone is being charged. One can achieve an automatic startup of the Mega synchronization by triggering it from .bashrc as follows:

if [ -n "$PS1" ]; then
    /bin/sh -eu /storage/2FD8-1F16/masysma/termux/ma_termux_server.sh &
    pidof sshd || sshd -p 8022
fi

Here, two commands are started if no suitable existent process could be found: The first ma_termux_server.sh serves two purposes:

  1. Detect loss of connectivity and then shutdown Termux to save battery power.
  2. Detect changes in files to synchronize and then calling rclone accordingly.

The second command starts SSHD if it is not already running.

ma_termux_server.sh

The script content is described in the following. It most likely needs some tuning to your use case and hence is not given as a complete file here. If you must, concatenate all the code listings in this subsection to retrieve it.

#!/bin/sh -eu
# Script to Manage Termux Servers 1.1.1, (c) 2022 Ma_Sys.ma <info@masysma.net>

sync_source=/storage/2FD8-1F16/masysma/mega
sync_target=mega:/
sync_marker_new="$sync_source/../mega_status/new"
sync_marker_inp="$sync_source/../mega_status/inp"
sync_log="$sync_source/../mega.log"

At the begin of the script, source and target of the synchronization are defined. Additionally, a sync_log location is defined to place the output of the rclone command. It is important to watch this log for anomalies.

has_network() {
    ipmsg="$(ip addr show dev eth0 || echo NOTHING)"
    if { echo "$ipmsg" | grep -qF ,UP,; } && \
            { echo "$ipmsg" | grep -qF "inet 192.168.1."; } && \
            ping -w 1 -c 1 192.168.1.1 > /dev/null 2>&1; then
        return 0
    else
        return 1
    fi
}

This routine is intended to check network connectivity. As in my example, the phone runs in network 192.168.1.0/24 with gateway 192.168.1.1 and network interface eth0 in Termux, it is natural to check these conditions by ping and ip

# -- Avoid Duplicate Instances --
# 3 is normal: myself, my subshell and my grep!
if [ "$(LINES=999 ps auxw | grep -cF "ma_termux_server")" -gt 3 ]; then
    echo ma_termux_server: already running. not starting another instance.
    exit 0
fi

This detects other running instances of the same script and avoids running multiple instances at once because that would probably wreck havoc with synchronization if it were to happen.

# -- Check Network Connectivity --
echo ma_termux_server: detecting online connectivity
ipstatus=0
while [ "$ipstatus" -lt 10 ] && ! has_network; do
    printf .
    sleep 5
done
if [ "$ipstatus" = 10 ]; then
    echo ma_termux_server: Internet connectivity did not appear in time. \
        Exiting script.
    exit 0
fi

As a preliminary step to running the script, network connectivity has to be in place. Here, this is checked explicitly in order to ensure that running Termux without connectivity does not needlessly engage the script.

# -- Mainloop --
head -n 2 "$0" | tail -n 1 | cut -c 3-
ipstatus=0
while [ "$ipstatus" -le 2 ]; do
    if has_network; then
        ipstatus=0
        if [ -f "$sync_marker_new" ] || [ -f "$sync_marker_inp" ]; then
            if [ -f "$sync_marker_new" ]; then
                mv -f "$sync_marker_new" "$sync_marker_inp"
            fi
            echo ma_termux_server: sync now
            if ! rclone sync -v "$sync_source" "$sync_target" 2>&1 \
                            | tee "$sync_log"; then
                echo ma_termux_server: sync failed. cancelled.
            fi
            rm "$sync_marker_inp"
        fi
    else
        echo "ma_online_status: about to lose connection ctr=$ipstatus."
        ipstatus=$((ipstatus + 1))
    fi
    sleep 30
done

The Mainloop checks the network connectivity every 30 sec. If it is present it continues to check the synchronization markers. If the new marker is present, it is renamed to inp (for in progress). Afterwards, the actual rclone call to sync source to target is invoked. Its output is redundantly printed to stdout and the logfile. At the end of the synchronization, the inp marker is deleted.

The semantics behind the two markers is as follows:

  1. new signals that new data has arrived.
  2. inp signals that synchronization is on-going.

The presence of any of the markers triggers a synchronization because:

# -- Termination --
echo ma_online_status: offline condition detected. Enter \`killall sleep\` to \
    avoid session exit in 1min.
sleep 60
am startservice -a com.termux.service_stop com.termux/.app.TermuxService
sleep 5
kill -s TERM $(ps -o pid | grep -vF PID) || true
sleep 1
kill -s KILL $(ps -o pid | grep -vF PID) || true

The final lines of the script are only entered when the phone is detected to be offline. In that case, multiple ways are tried to terminate the running Termux session since any single command was not found to be exactly effective in stopping it…

The Source System Side

To synchronize data to Mega by using the phone as a backup server, a client has to push data to the phone via SSH. A reliable way to achieve this is by using rsync. These commands and options work for me:

mdb_web_ip=192.168.1.102
export RSYNC_RSH="ssh -o Port=8022 -i .../id_ed25519"
mdb_web_target="u0_a162@$mdb_web_ip:/storage/2FD8-1F16/masysma/mega"
sshtarget="${mdb_web_target%:*}"
rsync -virhLWO --size-only --progress --delete \
                    sourcefiles... "$mdb_web_target"
$RSYNC_RSH "$sshtarget" touch "$sshdir/../mega_status/new" || true

Adjust this to your situation as follows

Termux:API

Sometimes, SMS-TAN are required. In order to access them via SSH, Termux:API provides a command to list SMS: termux-sms-list.

Be aware that after installing Termux:API, it must be “allowed” in NetGuard, oterhwise the network connectivity is no longer possible with the following observations: pings can be started, but no replies are received. Also wget/curl times out without connecting. IP addresses could still be resolved (as seen in ping output)…

See also: https://github.com/termux/termux-app/issues/2778

Things that did not work when tested

This chapter collects all the various notes from trying out things that did not work out in the end. They may serve as a starting point if you want to try any of these things.

You are encouraged to report progress on any of these topics to <info@masysma.net> if you happen to achieve success regarding any of the topics described in any of the following subsections.

Megacmd

It looks easy enough:

pkg install megacmd
mega-login email password
mega-sync /storage/2FD8-1F16/masysma/mega /

However, this turned out not to work reliably. The following erroneous behaviour was observed:

Hence, another approach was considered.

Commands for viewing the Mega status when using megacmd:

mega-sync
mega-transfers --show-syncs

Mega GUI Approach

Requires a lot of dependencies (tigervnc and icewm were intended to be used later for displaying the GUI). Note that this list was extended during compilation and is most likely still incomplete. Also note that Termux does not have separate -dev packages!:

pkg install x11-repo tigervnc icewm git build-essential wget unzip pkg-config binutils qt5-qtsvg qt5-qtx11extras qt5-qttools

Download and extract the Mega sources (maybe git clone --recursive https://github.com/meganz/MEGAsync.git).

Then perform a lot of patches. You can take some inspiration from the following listings although I did not achieve a successful compilation even with all of them applied…

Patch src/MEGASync/MEGASync.pro

Here we need to disable use drive notifications because udev is not available in Termux.

diff --git a/src/MEGASync/MEGASync.pro b/src/MEGASync/MEGASync.pro
index 75c8857e7..44690e976 100644
--- a/src/MEGASync/MEGASync.pro
+++ b/src/MEGASync/MEGASync.pro
@@ -111,7 +111,7 @@ else {
 }
 
 # Drive notifications (for SDK)
-CONFIG += USE_DRIVE_NOTIFICATIONS
+# CONFIG += USE_DRIVE_NOTIFICATIONS
 
 include(gui/gui.pri)
 include(mega/bindings/qt/sdk.pri)

Patch src/configure

Here we also remove -N (drive notification). Enable -y for dynamic linking.

diff --git a/src/configure b/src/configure
index 1d531a845..7e269ae63 100755
--- a/src/configure
+++ b/src/configure
@@ -73,24 +73,26 @@ shift $((OPTIND-1))
 # if archives are not yet downloaded
 if [ ! -d "$archives" ]; then
     mkdir $archives
-    ./MEGASync/mega/contrib/build_sdk.sh $FLAG_CRYPTOPP -n -N $FLAG_CARES $FLAG_LIBMEDIA $FLAG_CURL $FLAG_DISABLE_ZLIB $FLAG_RAW -w -s -v -u -o $archives
+    # MASYSMA CHANGES: Remove -N, Add -y
+    ./MEGASync/mega/contrib/build_sdk.sh -y $FLAG_CRYPTOPP -n $FLAG_CARES $FLAG_LIBMEDIA $FLAG_CURL $FLAG_DISABLE_ZLIB $FLAG_RAW -w -s -v -u -o $archives
     rm_archives=1
 fi
 
 cd MEGASync/mega
+# MASYSMA CHANGES: Remove -N, add -y
 ./contrib/build_sdk.sh \
     $FLAG_CRYPTOPP \
     -o $archives \
     $FLAG_CARES $FLAG_CURL $FLAG_LIBMEDIA $FLAG_DISABLE_ZLIB $FLAG_RAW \
     -l \
     -n \
-    -N \
     -c \
     -t \
     -s \
     -v \
     -I \
     -u \
+    -y \
     -p $root_dir/MEGASync/mega/bindings/qt/3rdparty

Patch src/MEGASync/mega/sdk_build/build/cryptopp820/config.h

This patch fixes some weird errors regarding intrinsics. It may not be needed since it may be possible to build without the vendored Crypto++ library by using a system-provided one instead. This patch was taken from https://github.com/cryfs/cryfs/issues/345. Similar patches may exist in other issues.

diff --git a/../vendor/cryptopp/vendor_cryptopp/config.h b/../../config.h
index 283c409..54ee6c2 100644
--- a/../vendor/cryptopp/vendor_cryptopp/config.h
+++ b/../../config.h
@@ -733,7 +733,7 @@ NAMESPACE_END
 // Limit the <arm_acle.h> include.
 #if !defined(CRYPTOPP_ARM_ACLE_AVAILABLE)
 # if defined(__aarch32__) || defined(__aarch64__) || (__ARM_ARCH >= 8) || defined(__ARM_ACLE)
-#  if !defined(__ANDROID__) && !defined(ANDROID) && !defined(__APPLE__)
+#  if !defined(__APPLE__)
 #   define CRYPTOPP_ARM_ACLE_AVAILABLE 1
 #  endif
 # endif

Patch src/MEGASync/mega/sdk_build/build/cryptopp820/GNUmakefile

In case of building with vendored Crypto++, it may be necessary to add the cpu-features.c and cpu-features.h files to the Crypto++ build directory. To make the build find them, change Crypto++ GNUmakefile accordingly.

I do not remember having to change the CC variable definition although it appears in the patch here…

--- GNUmakefile.orig    2019-04-29 01:36:50.000000000 +0200
+++ src/GNUmakefile.chg 2022-10-09 21:15:28.731611888 +0200
@@ -157,12 +157,6 @@
   ZOPT = -O0
 endif
 
-# On ARM we may compile aes_armv4.S though the CC compiler
-ifeq ($(GCC_COMPILER),1)
-  CC=gcc
-else ifeq ($(CLANG_COMPILER),1)
-  CC=clang
-endif
 
 # Default prefix for make install
 ifeq ($(PREFIX),)
@@ -1060,7 +1054,7 @@
 
 # List cryptlib.cpp first, then cpu.cpp, then integer.cpp to tame C++ static initialization problems.
 OBJS := $(SRCS:.cpp=.o)
-OBJS := $(OBJS:.S=.o)
+OBJS := $(OBJS:.S=.o) cpu-features.o
 
 # List test.cpp first to tame C++ static initialization problems.
 TESTSRCS := adhoc.cpp test.cpp bench1.cpp bench2.cpp bench3.cpp datatest.cpp dlltest.cpp fipsalgt.cpp validat0.cpp validat1.cpp validat2.cpp validat3.cpp validat4.cpp validat5.cpp validat6.cpp validat7.cpp validat8.cpp validat9.cpp validat10.cpp regtest1.cpp regtest2.cpp regtest3.cpp regtest4.cpp
@@ -1570,6 +1564,9 @@
 endif
 endif
 
+cpu-features.o: cpu-features.c
+   $(CC) $(strip $(CXXFLAGS) -c) $<
+
 validat1.o : validat1.cpp
    $(CXX) $(strip $(CXXFLAGS) $(ALTIVEC_FLAG) -c) $<

Patch src/MEGASync/mega/configure.ac

Removes another place with an udev dependency.

diff --git a/configure.ac b/configure.ac
index d7d3139cc..c72fe6503 100644
--- a/configure.ac
+++ b/configure.ac
@@ -318,7 +318,8 @@ AS_IF([test "x$enable_drive_notifications" = "xyes"], [
     CXXFLAGS="$CXXFLAGS -DUSE_DRIVE_NOTIFICATIONS"
     # Add lib to linker command
     if test "x$LINUX" = "xyes"; then
-        LDFLAGS="$LDFLAGS -ludev"
+   # was -ludev
+        LDFLAGS="$LDFLAGS"
     elif test "x$WIN32" = "xyes"; then
         LDFLAGS="$LDFLAGS -lwbemuuid"
     elif test "x$DARWIN" = "xyes"; then

Patch src/MEGASync/mega/contrib/build_sdk.sh

The original included a base64 encoded version of cpu-features.c and cpu-features.h to put into cryptopp directory. Its stats were as follows:

$ sha256sum cpu-features.?
cce1508673c364ee07ef1128e66e52bad99739e56b62dbc60c6e265510d565b1  cpu-features.c
c6c2107c5f2e3133c316e39e87148cb62dfc0bbcd887e338ff277e6281085b86  cpu-features.h

Here is the remainder of the patch (not directly applicable, do it by hand!):

     if [ $android_build -eq 1 ]; then
         cp ${ANDROID_NDK_ROOT}/sources/android/cpufeatures/cpu-features.h $cryptopp_dir/
         cp ${ANDROID_NDK_ROOT}/sources/android/cpufeatures/cpu-features.c $cryptopp_dir/
         package_build $name $cryptopp_dir "static -f GNUmakefile-cross"
         package_install $name $cryptopp_dir $install_dir $cryptopp_md5 "-f GNUmakefile-cross"
     else
-        package_build $name $cryptopp_dir static
+        package_build $name $cryptopp_dir static dynamic
         package_install $name $cryptopp_dir $install_dir $cryptopp_md5
    fi
 }
@@ -1058,7 +1060,7 @@ build_sdk() {
 
     # enable libuv
     if [ $enable_libuv -eq 1 ]; then
-        libuv_flags="--with-libuv=$install_dir"
+        libuv_flags="--with-libuv=/data/data/com.termux/files/usr"
     else
         libuv_flags="--without-libuv"
     fi

Patch `src/MEGASync/mega/src/gfx/freeimage.cpp

This patch is based on https://github.com/meganz/MEGAcmd/issues/632 and required to fix a compile issue:

diff --git a/src/gfx/freeimage.cpp b/src/gfx/freeimage.cpp
index eef623744..c94850b59 100644
--- a/src/gfx/freeimage.cpp
+++ b/src/gfx/freeimage.cpp
@@ -313,7 +313,7 @@ bool GfxProviderFreeImage::readbitmapFfmpeg(FileSystemAccess* fa, const LocalPat
 
     // Find decoder for video stream
     AVCodecID codecId = codecParm->codec_id;
-    AVCodec* decoder = avcodec_find_decoder(codecId);
+    auto decoder = avcodec_find_decoder(codecId);
     if (!decoder)
     {
         LOG_warn << "Codec not found: " << codecId;
@@ -330,7 +330,7 @@ bool GfxProviderFreeImage::readbitmapFfmpeg(FileSystemAccess* fa, const LocalPat
 
     // Force seeking to key frames
     formatContext->seek2any = false;
-    videoStream->skip_to_keyframe = true;
+    //videoStream->skip_to_keyframe = true;
     if (decoder->capabilities & CAP_TRUNCATED)
     {
         codecContext->flags |= CAP_TRUNCATED;

Try Build

./configure -g -i
qmake MEGASync/MEGASync.pro
lrelease MEGASync/MEGASync.pro
make

During the make call, build errors were observed. No solution was found beyond digging into the code to find out what’s the matter here…

Post-Build

These are intended (untested) commands for VNC setup:

echo \$vncStartup = \"exec /data/data/com.termux/files/usr/bin/icewm\" > $HOME/.vncrc
mkdir ../usr/etc/X11/icewm
printf "%s\n\n%s\n" "#!/bin/sh -e" "/usr/bin/megasync &" > /etc/X11/icewm/startup
chmod +x /etc/X11/icewm/startup

Bashrc planned addition (untested)

[ -n "$(pidof vncserver)" ] || vncserver -geometry 1024x768 :0 &

Advanced Autorun

So far, no means was found to automatically trigger Termux while charging. While this would seem to be possible using an app like Easer, it did not reliably trigger the opening of the Termux client even when configured in various ways.

This section retains some of the notes about this configuration for later re-use.

See Also


Ma_Sys.ma Website 5 (1.0.2) – no Flash, no JavaScript, no Webfont, no Copy Protection, no Mobile First. No bullshit. No GUI needed. Works with any browser.

Created: 2022/09/14 20:35:27 | Revised: 2024/10/20 12:41:09 | Tags: android, handy, kb, note, 120.088, termux | Version: 1.1.0 | SRC (Pandoc MD) | GPL

(c) 2022, 2023 Ma_Sys.ma info@masysma.net

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.