Android: boot on plug, launch app after boot, shutdown on condition
(Updated 2024-10-12) Part of the Volty MIR project, but can be used for non-interactive applications.Volty MIR - [M]ap + [I]intelligent [R]everse Camera
To display maps, I need a device that has:
- GNSS/GPS receiver
- Offline maps
- Video output
MHL (Mobile High Definition Link)
What I want the device to do is:
- Boot as soon as I start the car (i.e. device is connected to power).
- Launch a navigation app after booting.
- Shut down if the car is off for some time (i.e. device is not connected to power but has some battery left)
For the map/navigation application, I chose Organic Maps, as it is lightweight, has a great interface, and works offline. I have used it for many years now.
Organic Maps
Other options are:
OsmAnd - more customizable, the OG of OpenStreetMap navigation
Osmin - similar to Organic Maps, and works great on Linux (PinePhone etc.)
These instructions presume you have the latest android-platform-tools (mainly adb and fastboot).
Boot on plug
Through fastboot (recommended method)
This does not work on Samsung devices!Boot the device to fastboot mode (aka download mode) and run
fastboot oem off-mode-charge 0This worked for Google Nexus 7 tablet, and probably works for most Google devices.
Be careful with this - if battery gets too low, device will be stuck in an annoying constantly crashing reboot loop until it is sufficiently charged. See below for automatic shutdown on condition.
Magisk module
This is what I ended up doing.Root the device with Magisk, and then download and install Magisk Autoboot module.
Magisk Autoboot
Update: I previously could not get this to work with Android 7, but I believe this was due to a specific ROM I had installed. Clean Lineage 14, or Lineage 14 Optimized works.
playplm / plm / lpm
This is a somewhat strange way to boot some Samsung devices: It relies on replacing the binary that displays the battery charge animation with a script that (re)boots the device instead. Requires root.Go to /system/bin and find a file named "playplm", "plm", or "lpm". Then edit it to contain only:
#!/system/bin/sh /system/bin/rebootAlthough I did not find any of these files on my S5, a redditor confirmed this worked on their Galaxy S3.
Launch app after boot
Termux with Termux:Boot plugin
Termux is a terminal emulator for Android, which can run with and without root.I installed Termux and Termux:Boot via F-Droid, and ran Termux:Boot once to initialize it.
Termux on F-Droid
Termux:Boot on F-Droid
Some references:
Getting started with Termux
Termux:Boot plugin
Per instructions, I created a startup script
mkdir -p ~/.termux/boot nano ~/.termux/boot/start-maps.sh
#!/data/data/com.termux/files/usr/bin/sh am start app.organicmaps/.SplashActivity
Side note: how to find app name and activity
Easier way is to install and open Activity Launcher, find the app and its name, then find a list of activities it has, and find the main activity. Then use those names in the script above.Activity Launcher on F-Droid
In my case:
- App name is app.organicmaps
- Activity name is .SplashActivity
Another possibility is to get this information through ADB. Allow ADB access and connect mobile device to main machine. Run these commands on main machine.
Get a list of applications via ADB:
adb shell pm list packages -f -3Get a list of activities via ADB:
PACKAGE=package.name adb shell dumpsys package | grep -Eo $(printf "^[[:space:]]+[0-9a-f]+[[:space:]]+%s/[^[:space:]]+" "${PACKAGE}") | grep -oE "[^[:space:]]+$"
Tasker
I have not tried this. Might be easier if you don't like the terminal.- Create a Profile Event / System / Device Boot
- Create a Task with Action: App / Launch App / (select the app)
- Tasker also recommends adding Task - Wait for around 5 seconds first before doing other tasks to ensure that the system is ready after booting.
- Link the Profile to the Task
Easer
Easer is an open-source automation tool like Tasker. While it can be used for some scripting, I was unable to get it to launch Organic Maps on boot.Shutdown on condition
Update: ACC (advanced charging controller) Magisk module handles this much better. See belowPreviously, I implemented this using Termux, Termux:API and crontab. This requires root, because shutdown is a system function, and keeps a wakelock to run cron (which might and might not matter for your use case)
Root
I rooted my device using Magisk.Official Magisk GitHub repo
Battery status
To check the battery status, I used Termux and Termux:API extension.Termux:API on F-Droid
Termux API on Termux Wiki
To check battery status:
termux-battery-statusThis returns JSON, which can be parsed using jq.
pkg install jqNow I can extract the values I need, for example:
batt_pct=`termux-battery-status | jq -r '.percentage'` batt_status=`termux-battery-status |jq -r '.status'`
Shutdown
To shut down Android:su -c "reboot -p"
Note on shutdown commands
These are the various shutdown commands I found for Android.Most of them seem to run fine in user's Termux session, but when they are run as a part of a cronjob, they run slowly, are buggy, and sometimes reboot the phone instead of shutting down:
sudo reboot -p sudo /system/bin/svc power shutdown sudo /system/bin/svc power reboot -p sudo am start -a android.intent.action.ACTION_REBOOTSo stick with
su -c "reboot -p"
Script
Putting it all together: (with an extra spoken message using another API)#!/data/data/com.termux/files/usr/bin/sh batt_pct=`termux-battery-status | jq -r '.percentage'` batt_status=`termux-battery-status | jq -r '.status'` if [ $batt_pct -lt 60 ] && [ "$batt_status" = 'DISCHARGING' ] then termux-tts-speak 'Low power. Shutting down.' su -c "reboot -p" fiI put this in a file at
/data/data/com.termux/files/usr/bin/yaky-auto-shutdownThis directory is in $PATH, so no need to specify the full path in the future.
Test by running in Termux:
yaky-auto-shutdown
Automation
To automate this script, I used crontab. First, install it through Termux:pkg install cronieEdit crontab:
crontab -eAdd an entry to run the auto-shutdown script
* * * * * yaky-auto-shutdownTo run the cron daemon, add another script to execute at boot:
nano ~/.termux/boot/start-cron.sh
#!/data/data/com.termux/files/usr/bin/sh termux-wake-lock crondThis will set a wakelock to prevent Android from killing the long-running process, and then launch crond.
Every minute, cron will run the script, which will check the battery percentage and status, and shut down the device if the specified conditions are met. Although shutdown command requires root, root privileges will be provided to Termux as necessary (as long as they have been provided at least once before)
Battery management
All of these require root.ACC + app
Update: ACC (advanced charging controller) works pretty well, for both limiting the maximum charge level and for shutting down at a specific percentage. I used the simple version since I run Lineage 14 (Android 7).Advanced Charging Controller (ACC) on GitHub
The easiest way is to install ACCA from F-Droid, give it root access, and let it install the ACC daemon.
AccA on F-Droid
Battery Charge Limit app
Previously, to reduce wear and damage to an already-old battery, I installed Battery Charge Limit app to keep the device charge between 70% and 80%.Battery Charge Limit on F-Droid (this link is dead)
Battery Charge Limit on APKPure
Input Power Control
Similar to ACC but without the automatic shutdown. I did not try this.IP Control on GitHub
Simulating events
Having root allows calling Android's input command to simulate touch and keyboard events from the terminal.Note: Just like with the shutdown command above, it seems that the correct way to execute commands as root on Android is
su -c ""
Single tap:
su -c "input tap 500 1450"Swipe or long press:
su -c "input swipe 100 500 100 500 250"Exact screen locations can be found by enabling "Show pointer location" in Developer Settings.
For example, Organic Maps hides the UI on long-press, so I can call this after the app opens:
su -c "input swipe 500 500 500 500 1000"This simulates holding a finger at coordinate (100,100) for a second (1000 milliseconds).
Current issues
It appears that the MHL cable does not supply enough current (pun intended) to keep the device charged, so it is gradually losing battery charge even though it is plugged in. Battery status shows current of 300mA when charging via MHL cable, and 450mA when charging through a regular USB cable connected to a laptop USB port.I am considering combining the MHL USB cable with a regular charging USB cable, or going battery-less.
Topic on AndroidCentral
ROM and kernel
Lineage 14.1 (Android 7.1.2) Optimized ROMKernel for Samsung Galaxy S5 family
Final scripts
For my own reference.nano ~/.termux/boot/yaky-auto-start.sh
#!/data/data/com.termux/files/usr/bin/sh # Hold a wakelock for cron to run correctly termux-wakelock # Enable ssh server for easy access sshd # Enable cron for automatic shutdown crond # Start Organic Maps am start app.organicmaps/.SplashActivity # Wait for Organic Maps to start sleep 10 # Long-press the map to hide the UI su -c "input swipe 500 500 500 500 1000" # Announce readiness termux-volume music 10 termux-tts-speak 'Navigation ready'
nano /data/data/com.termux/files/usr/bin/yaky-auto-shutdown
#!/data/data/com.termux/files/usr/bin/sh # Extract battery percentage batt_pct=`termux-battery-status | jq -r '.percentage'` # Extract battery status batt_status=`termux-battery-status | jq -r '.status'` # Shut down when unplugged and below 60% if [ $batt_pct -lt 60 ] && [ "$batt_status" = 'DISCHARGING' ] then termux-tts-speak 'Low power. Shutting down.' su -c "reboot -p" fi
crontab -e
* * * * * yaky-auto-shutdown