#!/bin/sh

# adb_uiautomator.sh
# 2026-03-29
# by Gernot Walzl

# Up to now, this is just an idea on
# how to tap buttons of various apps over adb.
# The device needs to be in unlocked state.

# Requirements:
# apt install adb libxml2-utils

# Notice: The position in xpath is 1-based, not 0-based.

set -e

restart_app () {
  APP=$1
  adb shell "am stop-app '$APP'"
  adb shell "am start '$APP'"
}

stop_app () {
  APP=$1
  adb shell "am stop-app '$APP'"
}

input_tap () {
  XPATH=$1
  read X_MIN Y_MIN X_MAX Y_MAX <<EOF
$(adb exec-out "uiautomator dump /dev/tty > /dev/null" \
  | xmllint --xpath "$XPATH/@bounds" - \
  | sed 's/.*\[\(.*\),\(.*\)\]\[\(.*\),\(.*\)\].*/\1 \2 \3 \4/')
EOF
  if [ -z "$Y_MAX" ]; then
    echo "WARNING: '$XPATH' not found."
    return 1
  else
    adb shell "input tap $((($X_MIN + $X_MAX)/2)) $((($Y_MIN + $Y_MAX)/2))"
  fi
}

input_text () {
  adb shell "input text '$1'"
}

export_contacts () {
  FILENAME="contacts-$(date '+%Y-%m-%d').vcf"
  adb shell "rm '/sdcard/$FILENAME'"
  restart_app 'com.android.contacts'

  input_tap '//node[@resource-id="com.android.contacts:id/toolbar"]/node[1]'
  input_tap '//node[@resource-id="com.android.contacts:id/nav_settings"]'
  input_tap '//node[@package="com.android.contacts" and @resource-id="android:id/list"]/node[9]'
  input_tap '//node[@package="com.android.contacts" and @resource-id="android:id/select_dialog_listview"]/node[1]'
  input_tap '//node[@resource-id="com.android.documentsui:id/horizontal_breadcrumb"]/node[1]/node[1]'
  input_tap '//node[@resource-id="com.android.documentsui:id/container_save"]/node[1]/node[2]'
  input_text "$FILENAME"
  input_tap '//node[@resource-id="com.android.documentsui:id/container_save"]/node[1]/node[3]'

  sleep 5
  adb pull "/sdcard/$FILENAME"
  stop_app 'com.android.contacts'
}

export_contacts
