Skip to main content

Command Android Apps from Python

Python 3.10 License: AGPL v3 Code Style: Black Code Coverage

Uses uiautomator to automatically and safely control and navigate Android apps. The user can specify some app logic (series of screens and button clicks) that is executed on your Android phone through ADB.

Why

I wanted self-host my Nextcloud calendar with 1 command, from anywhere in the world, no port-forwarding, no DNS stuff, no domain-name, no registrar configuration no nothing. That includes complete Android phone configuration automation for me. Some apps did not have, and perhaps may not want, a configuration API. Configuring Android apps with automated key-presses is not safe because an unexpected event may come up, e.g. a prompt for a phone update, a call may come in etc.

So I wanted a safe- and controlled way to configure the app, using the UI. This repository verifies each step in an arbitrary script, verifies the button is the desired button etc. If unexpected changes are expected, the script aborts.

Also, each phone manufacturer has a different rooting process, this repo can become a library to safely- and automatically root all (rootable) Android phones automatically (except the user must enable ADB themselves).

Example

image

Usage

First satisfy the prerequisites:

pip install appcommander

Connect your phone, and tell this code which app you want to automate, and how:

python -m src.appcommander -a org.torproject.android -v "16.6.3 RC 1" -t "DAVx5"
appcommander -a org.torproject.android -v "16.6.3 RC 1" -t DAVx5

which is the same as:

python -m src.appcommander --app-name org.torproject.android \
--version "16.6.3 RC 1" -torify "DAVx5"

Or, to configure DAVx5:

python -m src.appcommander -a at.bitfire.davdroid -v "4.2.6" -nu \
<your_nextcloud_username> -np <your_nextcloud_password> -o <your_onion_url>

For more info, run:

python -m src.appcommander --help

Testing

One can simulate an android phone with:

chmod +x emulate_android.sh
./emulate_android.sh

And then launch the emulated android phone with:

. ~/.profile
cd ~/.android/avd/android-small.avd/
rm *.lock
emulator -avd android-small -netdelay none -netspeed full -skin 768x1280

And run tests with:

python -m pytest

or to see live output, on any tests filenames containing substring: results:

python -m pytest --capture=tee-sys

Test Coverage

Developers can use:

conda env create --file environment.yml
conda activate appcommander
python -m pytest

Currently the test coverage is 65%. For type checking:

mypy --disallow-untyped-calls --disallow-untyped-defs tests/some_test.py

Releasing pip package update

To udate the Python pip package, one can first satisfy the following requirements:

pip install --upgrade pip setuptools wheel
pip install twine

Followed by updating the package with:

rm -r dist
rm -r build
python3 setup.py sdist bdist_wheel
python -m twine upload dist/\*

Developer pip install

mkdir -p ~/bin
cp apk-ct.sh ~/bin/apk-ct
chmod +x ~/bin/apk-ct

Then you can rebuild and locally re-install the appcommander pip package the command:

apk-ct

Updating

Build the pip package with:

pip install --upgrade pip setuptools wheel
pip install twine

Install the pip package locally with:

rm -r dist
rm -r build
python -m build
pip install -e .

Upload the pip package to the world with:

rm -r dist
rm -r build
python -m build
python3 -m twine upload dist/\*

that installs the latest changes into the pip package locally (into your conda environment).

Show your app-flow

To show how your script works, run (along with any additional input args required for that script):

python -m src.appcommander -a <package_name> -v <app_version> -f \
<additional arguments>

For example:

python -m src.appcommander -a "at.bitfire.davdroid" -v "4.2.6" -f  -nu \
<some_filler> -np <some_filler> -o <some_filler>
python -m src.appcommander -a "at.bitfire.davdroid" -v "4.2.6" -f -nu \
asdf -np asdf -o asdf
python -m src.appcommander -a org.torproject.android -v "16.6.3 RC 1" \
-f -t "DAVx5"

Release files for appcommander 0.0.35

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for appcommander 0.0.35
File Size Uploaded
appcommander-0.0.35.tar.gz 43.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for appcommander 0.0.35
File Interpreter ABI Platform
appcommander-0.0.35-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 109.9 kB

Release files / appcommander-0.0.35.tar.gz

Download URL appcommander-0.0.35.tar.gz
Size 43.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f2e649ea4282b8bbf7d7cada7f5db1a62deb213dc1cf62e7cb6fa598ba2d3019
BLAKE2b-256 checksum
How to use checksums
7694f5a57bc517fd4a97efbfe5b66099cbe0666703eaa7e3fcee47dbb583d787
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.10.9

Release files / appcommander-0.0.35-py2.py3-none-any.whl

Download URL appcommander-0.0.35-py2.py3-none-any.whl
Size 66.6 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
60e2b4781e88e857affbd2f7483cbbf81bbda41dc7085df1d0bd26aaa791d185
BLAKE2b-256 checksum
How to use checksums
0cfdd0a4b399bc86ecac8684000994395bbba522d1012f91f836e949e83f0ebf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.10.9
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page