#!/usr/bin/env bash # Replace an app with a differently signed build while keeping its data, permissions, # installer and frozen state. Data is also saved to BACKUP_DIR before the uninstall. # Usage: reinstall-keep-data.sh PACKAGE BACKUP_DIR APK [APK ...] set -euo pipefail pkg=$1 bak=$2; shift 2 a() { adb shell "$@" /dev/null'" > "$bak/$pkg.tar" echo "saved $(stat -c %s "$bak/$pkg.tar") bytes to $bak/$pkg.tar" [ "$(stat -c %s "$bak/$pkg.tar")" -gt 10240 ] || { echo "backup suspiciously small, aborting"; exit 1; } a "pm uninstall $pkg" iopt=(); [ -n "$installer" ] && [ "$installer" != null ] && iopt=(-i "$installer") adb install-multiple -r "${iopt[@]}" --bypass-low-target-sdk-block "$@" uid=$(su_ "stat -c %u /data/data/$pkg") cache_gid=$((uid - 10000 + 20000)) adb exec-in "su -c 'tar -xf - -C /'" < "$bak/$pkg.tar" su_ "while pgrep -x tar >/dev/null; do sleep 0.3; done" for d in /data/data/$pkg /data/user_de/0/$pkg; do su_ "chown -R $uid:$uid $d; for c in cache code_cache; do mkdir -p $d/\$c; chown $uid:$cache_gid $d/\$c; chmod 2771 $d/\$c; done; chcon -hR \"\$(stat -c %C $d)\" $d" done case " $dirs " in *Android/data*) su_ "d=/data/media/0/Android/data/$pkg; chown -R $uid:1078 \$d; find \$d -type d -exec chmod 2770 {} +; find \$d -type f -exec chmod 660 {} +; chcon -R u:object_r:media_rw_data_file:s0 \$d" ;; esac for p in $perms; do a "pm grant $pkg $p" 2>/dev/null || true; done [ "$disabled" = 1 ] && su_ "pm disable-user --user 0 $pkg" echo "$pkg: reinstalled as uid $uid, $(a "dumpsys package $pkg" | grep -m1 versionName | xargs)"