diff --git a/debloat_script.sh b/debloat_script.sh index 12bd081..f1b4d02 100755 --- a/debloat_script.sh +++ b/debloat_script.sh @@ -1,13 +1,12 @@ #!/usr/bin/env bash -# BASH 4.3 or newer is needed ! (use of local -n) -if (( BASH_VERSINFO < 5 )); then printf "\n%s\n\n" "Please upgrade to a bash version >= 4.3" && exit 1; fi +# BASH 4.4 or newer is needed! +if (( "${BASH_VERSINFO[0]}" < 5 )); then printf "\n%s\n\n" "Please upgrade to a bash version >= 4.4" && exit 1; fi if ! adb get-state &>/dev/null; then printf "\n%s\n\n" "Your phone is not detected by ADB." && exit 1; fi -set -euo pipefail # Safer bash script +set -Eeuo pipefail # Safer bash script -# Colors used for printing readonly BRED='\033[1;31m' # Bold + Red readonly BBLUE='\033[0;34m' # Bold + Blue readonly BGREEN='\033[1;32m' @@ -17,11 +16,11 @@ readonly Bold=$(tput bold) readonly nBold=$(tput sgr0) # Trap error -trap 'catch' EXIT +trap 'catch $LINENO' ERR catch() { (( $? == 0 )) && exit 0; - printf "\n\n${BRED}%s\n" "[EXIT TRAP] Hum... something is wrong." + printf "\n\n${BRED}%s\n" "[EXIT TRAP] Hum... something is wrong. Error on line $1" printf "\n%s\n" "If you think this is a bug. Please report it :)" printf "%s${NC}\n\n" "==> https://gitlab.com/W1nst0n/universal-android-debloater/-/issues" } @@ -34,40 +33,44 @@ done ############################################### MAIN SCRIPT ########################################################## main() { - - readonly VERSION="v2.7 (October 4th 2020)" + readonly SRC_URI="https://gitlab.com/W1nst0n/universal-android-debloater/-/archive/master/universal-android-debloater-master.tar.gz" + readonly VERSION="v2.8 (January 10th 2021)" readonly PAD=$(((48-${#VERSION})/2)) readonly BRAND="$(get_brand)" readonly BRAND_SUPPORTED=$( declare -p "$BRAND" &>/dev/null && echo "1" || echo "0") - # Legacy support - readonly OLDER_THAN_ANDROID_7_1=$(( $(adb shell getprop ro.build.version.sdk | tr -d '\r') < 26 )) + readonly OLDER_THAN_ANDROID_8=$(( $(adb shell getprop ro.build.version.sdk | tr -d '\r') < 26 )) readonly OLDER_THAN_ANDROID_5=$(( $(adb shell getprop ro.build.version.sdk | tr -d '\r') < 21 )) - readonly OPTION_NEEDED=$( ((OLDER_THAN_ANDROID_5)) && echo "" || echo "--user 0" ) - declare -a CUSTOM_LIST=() - declare -a EXTERNAL_LIST=() + declare -a CUSTOM_LIST=() # Trimed APK/package list from the debloat lists only containing packages/APK on the device (populated by generate_custom_list()) + declare -a EXTERNAL_LIST=() # APK/package list provided by the user (populated by import_external_list()) + declare -a USERS=() # User list (populated by debloat_or_restore()) + declare -ra LISTS=(us_carriers french_carrier german_carriers "$BRAND" google facebook amazon microsoft \ + qualcomm mediatek misc aosp pending) - FORCE_UNINSTALL=0 - RESTORE=0 + declare -i FORCE_UNINSTALL=0 + declare -i RESTORE=0 + declare -i ROOT=0 clear - echo " ================================================" - echo " # #" - echo " # UNIVERSAL ANDROID DEBLOAT SCRIPT #" - echo " # #" - printf " %-${PAD}s${BRED}%s${NC}%${PAD}s\n" "#" "${VERSION}" "#" - echo " # #" - echo " ================================================" - echo - printf "${Bold}%s\n\n" "Please carefully read the FAQ before using this script!" - printf "%s${nBold} " "Do you want to do an ADB backup ? [Y/N]" + printf "\n${BORANGE}%s\n" "================================================" + printf "%s\n" "# #" + printf "%-8s${NC}%s${BORANGE}%8s\n" "#" "UNIVERSAL ANDROID DEBLOAT SCRIPT" "#" + printf "%s\n" "# #" + printf "%-${PAD}s${BRED}%s${BORANGE}%${PAD}s\n" "#" "${VERSION}" "#" + printf "%s\n" "# #" + printf "%s${NC}\n\n" "================================================" + printf "${Bold}%s\n\n" "Please carefully read the FAQ before using this script!" + + if [[ $(adb get-state) = "recovery" ]]; then uad_recovery_mode || exit; fi + + printf "%s${nBold} " "Do you want to do an ADB backup ? [Y/N]" read -r if [[ $REPLY =~ [Yy]+[Ee]*[Ss]* ]]; then backup; fi - if (( OLDER_THAN_ANDROID_7_1 )); then + if (( OLDER_THAN_ANDROID_8 )); then clear printf "\n${BRED}%s " "WARNING : Your android version is too old (< 8.0)." printf "%s${NC}\n\n" "Uninstalled packages can't be restored." @@ -82,17 +85,20 @@ main() { adb shell 'pm list packages -s' | sed 's/package://g' > remaining_packages.txt & - clear - printf "\n${BORANGE}%s\n" "=================== MAIN MENU ===================" - printf "%s\n" "# #" - printf "%-14s${NC}%s${BORANGE}%16s\n" "#" "0 - Packages search" "#" - printf "%-14s${NC}%s${BORANGE}%15s\n" "#" "1 - Restore a backup" "#" - printf "%-14s${NC}%s${BORANGE}%15s\n" "#" "2 - Restore packages" "#" - printf "%-14s${NC}%s${BORANGE}%15s\n" "#" "3 - Debloat packages" "#" - printf "%s\n" "# #" - printf "%-14s${NC}%s${BORANGE}%6s\n" "#" "X - Exit and reboot the phone" "#" - printf "%s\n" "# #" - printf "%s${NC}\n\n" "===================================================" + clear -x + printf "\n${BORANGE}%s\n" "================== MAIN MENU ==================" + printf "%s\n" "# #" + printf "%-12s${NC}%s${BORANGE}%16s\n" "#" "0 - Packages search" "#" + printf "%-12s${NC}%s${BORANGE}%15s\n" "#" "1 - Restore a backup" "#" + printf "%-12s${NC}%s${BORANGE}%15s\n" "#" "2 - Restore packages" "#" + printf "%-12s${NC}%s${BORANGE}%15s\n" "#" "3 - Debloat packages" "#" + printf "%s\n" "# #" + printf "%-12s${NC}%s${BORANGE}%12s\n" "#" "4 - Restore APKs (Root)" "#" + printf "%-12s${NC}%s${BORANGE}%12s\n" "#" "5 - Debloat APKs (Root)" "#" + printf "%s\n" "# #" + printf "%-12s${NC}%s${BORANGE}%6s\n" "#" "X - Exit and reboot the phone" "#" + printf "%s\n" "# #" + printf "%s${NC}\n\n" "=================================================" printf "${BRED}%s${NC}\n\n" "DON'T FORGET TO REBOOT YOUR PHONE ONCE THE DEBLOAT IS OVER." @@ -102,37 +108,46 @@ main() { elif [[ $REPLY = 1 ]]; then restore_backup; - elif [[ $REPLY = 2 || $REPLY = 3 ]]; then - clear + elif [[ $REPLY = 2 || $REPLY = 3 || $REPLY = 4 || $REPLY = 5 ]]; then + clear -x (( !BRAND_SUPPORTED )) && printf "\n${BRED}%s\n" "No $BRAND debloat list found. Feel free to contribute ! :)" - [[ $REPLY = 2 ]] && { title="RESTORE"; RESTORE=1; } || { title="DEBLOAT"; RESTORE=0; } + case $REPLY in + 2) { title="RESTORE"; RESTORE=1; };; + 3) { title="DEBLOAT"; RESTORE=0; };; + 4) { title="RESTORE"; RESTORE=1; ROOT=1;};; + 5) { title="DEBLOAT"; RESTORE=0; ROOT=1;};; + esac - printf "\n${BORANGE}%s\n" "==================== $title ====================" - printf "%s\n" "# #" - printf "%-14s${NC}%s${BORANGE}%14s\n" "#" "1 - $title a package" "#" | awk '{print tolower($0)}' - (( BRAND_SUPPORTED )) && printf "#${NC}%10s 2 - ${BRAND} %$((25-${#BRAND}))s ${BORANGE} #\n" - printf "%-14s${NC}%s${BORANGE}%27s\n" "#" "3 - GFAM" "#" - printf "%-14s${NC}%s${BORANGE}%23s\n" "#" "4 - Carriers" "#" - printf "%-14s${NC}%s${BORANGE}%25s\n" "#" "5 - Others" "#" - printf "%-14s${NC}%s${BORANGE}%27s\n" "#" "6 - AOSP" "#" - printf "%-14s${NC}%s${BORANGE}%18s\n" "#" "7 - External list" "#" - printf "%s\n" "# #" - printf "%-14s${NC}%s${BORANGE}%15s\n" "#" "0 - Pending list /!\\" "#" - printf "%s\n" "# #" - printf "%s\n${NC}" "===================================================" + ((!ROOT)) && printf "\n${BORANGE}%s\n" "=================== $title ===================" + (( ROOT )) && printf "\n${BORANGE}%s\n" "================ $title (ROOT) ===============" + printf "%s\n" "# #" + printf "%-12s${NC}%s${BORANGE}%14s\n" "#" "1 - $title a package" "#" | awk '{print tolower($0)}' + (( BRAND_SUPPORTED )) && printf "#${NC}%8s 2 - ${BRAND} %$((25-${#BRAND}))s ${BORANGE} #\n" + printf "%-12s${NC}%s${BORANGE}%27s\n" "#" "3 - GFAM" "#" + printf "%-12s${NC}%s${BORANGE}%23s\n" "#" "4 - Carriers" "#" + printf "%-12s${NC}%s${BORANGE}%25s\n" "#" "5 - Others" "#" + printf "%-12s${NC}%s${BORANGE}%27s\n" "#" "6 - AOSP" "#" + printf "%-12s${NC}%s${BORANGE}%18s\n" "#" "7 - External list" "#" + (( ROOT && !RESTORE )) && printf "#${NC}%7s 8 - Create a flashable zip${BORANGE}%7s #\n" + printf "%s\n" "# #" + printf "%-12s${NC}%s${BORANGE}%15s\n" "#" "0 - Pending list /!\\" "#" + printf "%s\n" "# #" + printf "%s\n${NC}\n" "=================================================" - read -r -p "Your selection (e.g: 2 3 4 5): " - echo - if [[ "$REPLY" =~ 7 ]]; then import_external_list && debloat_or_restore EXTERNAL_LIST "external list"; fi + read -r -p "Your selection (e.g: 2 3 4 5): " + + if [[ "$REPLY" =~ 7 ]]; then import_external_list && debloat_or_restore EXTERNAL_LIST; fi if [[ "$REPLY" =~ 4 ]]; then lists_selection us_carriers french_carriers german_carriers; fi if [[ "$REPLY" =~ 3 ]]; then lists_selection google facebook amazon microsoft; fi if [[ "$REPLY" =~ 1 ]]; then debloat_or_restore; fi - if [[ "$REPLY" =~ 2 ]]; then generate_custom_list "$BRAND" && debloat_or_restore CUSTOM_LIST "$BRAND"; fi - if [[ "$REPLY" =~ 5 ]]; then lists_selection qualcomm misc; fi - if [[ "$REPLY" =~ 6 ]]; then generate_custom_list aosp && debloat_or_restore CUSTOM_LIST aosp; fi - if [[ "$REPLY" =~ 0 ]]; then generate_custom_list pending && debloat_or_restore CUSTOM_LIST pending; fi + if [[ "$REPLY" =~ 2 ]]; then debloat_or_restore "$BRAND"; fi + if [[ "$REPLY" =~ 5 ]]; then lists_selection qualcomm mediatek misc; fi + if [[ "$REPLY" =~ 6 ]]; then debloat_or_restore aosp; fi + if [[ "$REPLY" =~ 8 ]]; then create_flashable_zip; fi + if [[ "$REPLY" =~ 0 ]]; then debloat_or_restore pending; fi + elif [[ "$REPLY" =~ [Xx] ]]; then adb reboot && exit 0; @@ -142,82 +157,278 @@ main() { ############################################ END OF MAIN SCRIPT ###################################################### -import_external_list(){ +import_external_list() { local path="" - printf "\n${BRED}%s${NC}" "Path to the list : " - read -r path - readarray -t EXTERNAL_LIST < "$path" + while true; do + printf "\n${BRED}%s${NC}" "Path to the list: " + read -r path + if readarray -t EXTERNAL_LIST < "$path"; then break; fi + done + + for i in "${EXTERNAL_LIST[@]}"; do + if [[ ROOT -eq 1 && $i =~ ^/.*\.apk$ ]]; then + printf "\n${BRED}%s${NC}\n\n" "Please use a package list, not an APK list" + exit 1 + elif [[ ROOT -eq 0 && ! $i =~ ^[a-z][a-zA-Z0-9_]*(\.[a-zA-Z0-9_]+)+[0-9a-zA-Z_]$ ]]; then + printf "\n${BRED}%s${NC}%s${BRED}%s${NC}%s\n\n" "$i" " is not a package (format is" " com.android.bips" ")" + exit 1 + fi + done } +associate_path_with_package() { + local -n ASSOCIATE="$1" + declare -a PACKAGES=() + readarray -t PACKAGES < <(adb shell 'pm list packages -s -u -f' | sed -r 's/package://g' | sort -i) + + for i in "${PACKAGES[@]}"; do + ASSOCIATE["${i##*=}"]="${i%%=*}" + done +} -generate_custom_list(){ - [[ -v "$1" ]] && local -n list=$1 +generate_custom_list() { + local -n list="$1" + [[ $# -eq 2 ]] && local user_id="$2" + CUSTOM_LIST=() - if (( RESTORE == 1 )); then - readarray -t CUSTOM_LIST < <(comm -12 <(for p in "${list[@]}"; do echo "${p}"; done|sort -i) \ - <(adb shell 'pm list packages -s -u' | sed -r 's/package://g' | sort -i)) + if (( ROOT )); then + declare -A PACKAGE_AND_PATH=() # PACKAGE_AND_PATH[package]=path/to/apk + declare -a TEMP=() + associate_path_with_package PACKAGE_AND_PATH + + readarray -t TEMP < <(comm -12 <(for p in "${list[@]}"; do echo "${p}"; done|sort -i) \ + <(for p in "${!PACKAGE_AND_PATH[@]}"; do echo "$p"; done|sort -i)) + + for p in "${TEMP[@]}"; do + CUSTOM_LIST+=("${PACKAGE_AND_PATH[$p]}") + done + + [[ RESTORE -eq 1 ]] && readarray -t CUSTOM_LIST < <(comm -12 <(for p in "${CUSTOM_LIST[@]}"; do echo "${p}"; done|sort -i) \ + <(sort -i deleted_apks.txt)) else - readarray -t CUSTOM_LIST < <(comm -12 <(for p in "${list[@]}"; do echo "${p}"; done|sort -i) \ - <(sort -i remaining_packages.txt)) + if (( RESTORE )); then + readarray -t CUSTOM_LIST < <(comm -12 <(for p in "${list[@]}"; do echo "${p}"; done|sort -i) \ + <(adb shell "pm list packages -s -u $user_id" | sed -r 's/package://g' | sort -i)) + else + readarray -t CUSTOM_LIST < <(comm -12 <(for p in "${list[@]}"; do echo "${p}"; done|sort -i) \ + <(adb shell "pm list packages -s $user_id" | sed 's/package://g' | sort -i)) + fi fi + return 0 } debloat_or_restore() { local action="" # restore or debloat local output="" - title=$( echo "$title" | tr '[:upper:]' '[:lower:]') - - (( RESTORE )) && action="cmd package install-existing \$package" || action="pm uninstall $OPTION_NEEDED \$package" + local title=$( echo "$title" | tr '[:upper:]' '[:lower:]') # Android 7.1 and older can't reinstall packages - if (( OLDER_THAN_ANDROID_7_1 )) && (( !FORCE_UNINSTALL )); then - (( RESTORE )) && action="pm enable \$package" || action="am force-stop \$package \&\& pm disable-user \$package \&\& pm clear \$package" + if (( OLDER_THAN_ANDROID_8 )); then + (( RESTORE )) && action='pm enable $package' || action='am force-stop $package && pm disable-user $package && pm clear $package' fi - clear + (( RESTORE && FORCE_UNINSTALL == 1 )) && action='cmd package install-existing $package' || action='pm uninstall $user $package' + # parse user list on the phone + readarray -t USERS < <(adb shell pm list users | grep -o "{[0-9]*" | grep -o "[0-9]*") + + clear -x if [[ $# -gt 0 ]]; then + local list="$1" - local -n list=$1 # list is a nameref. Array is passed by reference. + printf "\n${BORANGE}%s${NC}\n" "==== $list debloat list ====" - printf "\n${BORANGE}%s${NC}\n" "==== $2 debloat list ====" - (( ! ${#CUSTOM_LIST[@]} )) && echo "Nothing to $title :)" && sleep 1 && return 0 + if (( ROOT )); then + generate_custom_list "$list" + if (( RESTORE )); then restore_apks "$list"; else root_debloat "$list"; fi + return + fi - for package in "${list[@]}"; do - printf "${BRED}%s${NC} " "$package -->" - output=$(eval adb shell "$action") && echo "$output" - if ! [[ "$output" =~ "Failure" ]] && [[ $RESTORE -eq 0 ]]; then echo "$package" >> "debloated_packages.txt"; fi + for u in "${USERS[@]}"; do + local user=$( ((OLDER_THAN_ANDROID_5)) && echo "" || echo "--user $u" ) + generate_custom_list "$list" "$user" + + if [[ ${#CUSTOM_LIST[@]} -eq 0 ]]; then + printf "${BBLUE}%s${NC}%s" "[user $u]" " Nothing to $title :)" && sleep 1 && continue + fi + + for package in "${CUSTOM_LIST[@]}"; do + do_package_action_and_log "$package" "$action" "$u" + done done + sleep 1 else - printf "\n${BRED}%s${NC}" "Package name to $title : " - read -r package - printf "${BRED}%s${NC}" "$package --> " - output="$(eval adb shell "$action")" || true - echo "$output" - if ! [[ "$output" =~ Failure|Error ]] && (( !RESTORE )); then echo "$package" >> "debloated_packages.txt"; fi - sleep 2 + if (( ROOT )); then + if (( RESTORE )); then restore_apks; else root_debloat; fi + return + fi + printf "\n${BRED}%s${NC}" "Package name to $title: " + read -r package + for u in "${USERS[@]}"; do + local user=$( ((OLDER_THAN_ANDROID_5)) && echo "" || echo "--user $u" ) + do_package_action_and_log "$package" "$action" "$u" + done + sleep 1 + fi +} + +do_package_action_and_log() { + local package="$1" + local action="$2" + local user="$3" + printf "${BBLUE}%s${BRED}%s${NC}%s" "[user $user] " "$package --> " + output="$(eval adb shell "$action")" && echo "$output" + + if [[ ! "$output" =~ Failure|Error ]]; then + if [[ $RESTORE -eq 0 ]]; then + grep -qxF "$package" debloated_packages.txt || echo "$package" >> "debloated_packages.txt" + else + grep -qFv "$package" debloated_packages.txt > temp.tmp || touch temp.tmp; mv temp.tmp debloated_packages.txt + fi + fi +} + +backup_apks() { + printf "\n%s${BRED}%s${NC}%s\n\n" "Your apks are beeing backed-up in" " apks_backup/" " (in case you mess up)" + local -n apks="$1" + mkdir -p apks_backup + for apk in "${apks[@]}"; do + adb pull "$apk" apks_backup/ + done + printf "\n${BRED}%s${NC}\n\n" "Backup done!" +} + +create_flashable_zip() { + clear -x + declare -a selection=() + + echo + for i in "${!LISTS[@]}"; do + printf "%-2s%s\n" "$i" " - ${LISTS[$i]}" + done + + printf "\n${BRED}%s${NC} " "Your choice (e.g 1 2 3) :" + read -r -a selection + + echo "#!/sbin/sh" > root_debloat_script.sh + + declare -i is_empty=1 + + for list in "${selection[@]}"; do + if (( list > ${#LISTS[@]} )) || (( list < 1 )); then continue; fi + generate_custom_list "${LISTS[$list]}" + + for package in "${CUSTOM_LIST[@]}"; do + echo "rm -rf $package" >> root_debloat_script.sh + done + [[ $is_empty -eq 1 && ${#CUSTOM_LIST[@]} -gt 0 ]] && is_empty=0 + done + + if [[ $is_empty -eq 1 ]]; then + printf "\n${BRED}%s${NC}\n" "Nothing to debloat!" + rm root_debloat_script.sh + else + if [[ ! -e META-INF/com/google/android/updater-binary ]]; then + printf "\n${BBLUE}%s${NC}%s\n" "META-INF/com/google/android/updater-binary" " is missing!" + else + zip -r flashable_zip_UAD_v2.8.zip META-INF/ root_debloat_script.sh 1>/dev/null + printf "\n${BRED}%s${NC}%s\n" "flashable_zip_UAD_v2.8.zip" " has been generated." + fi + fi + + sleep 2 +} + +restore_apks() { + declare -a path=() + + if [[ $# -eq 1 ]]; then + + [[ ${#CUSTOM_LIST[@]} -eq 0 ]] && echo "Nothing to restore" && sleep 1 && return 0 + + printf "\n%s${BBLUE}%s${NC}%s${BBLUE}%s${NC}\n\n" "Deleted apks from " "$list" " will be restored from " "apks_backups/" + printf "\n${BRED}%s${NC}\n\n" "Check your phone: Magisk Manager is probably asking you to grand root permissions for ADB" + + else + printf "\n%s${BRED}%s${NC}%s" "Android Path of the APK to restore (the APK will be restored from " "apks_backups/" "): " + read -r path + if [[ ! $path =~ ^/.*\.apk$ ]]; then + printf "\n${BRED}%s${NC}%s${BRED}%s${NC}%s\n" "$path" "doesn't look like a valid APK path" + sleep 2 && return 0 + fi + CUSTOM_LIST=("$path") + fi + + adb shell "su -c 'mount -o rw,remount /system'" + + + for p in "${CUSTOM_LIST[@]}"; do # $p = path/to/app.apk + local apk=$(echo "$p" | sed -r 's/.*\///g') # app.apk + local dir=$(dirname "$p") # path/to + if adb push "apks_backup/$apk" /sdcard && adb shell "su -c 'mkdir -p \"$dir\"; mv \"/sdcard/$apk\" \"$dir\"; chmod 644 \"$p\"'"; then + grep -Fqv "$p" deleted_apks.txt > temp.tmp || touch temp.tmp; mv temp.tmp deleted_apks.txt + fi + done + + adb shell "su -c 'mount -o ro,remount /system'" + printf "\n${BRED}%s${NC}%s\n" "Reboot your phone and Android will reinstall the app(s)" + printf "\n\e[5m%s\033[0m" "Press any key to continue" + read -n 1 -r -s +} + +root_debloat() { + if [[ $# -eq 1 ]]; then + + [[ ${#CUSTOM_LIST[@]} -eq 0 ]] && echo "Nothing to debloat :)" && sleep 1 && return 0 + + backup_apks CUSTOM_LIST + else + printf "\n${BRED}%s${NC}" "Android Path of the APK to delete: " + read -r path + if [[ ! $path =~ ^/.*\.apk$ ]]; then + printf "\n${BRED}%s${NC}%s${BRED}%s${NC}%s\n" "$path" " doesn't look like a valid APK path" + sleep 2 && return 0 + fi + CUSTOM_LIST=("$path") + fi + + read -r -p "Type YES if you want to physically delete the apks: " + if [[ $REPLY = "YES" ]]; then + local commandes="mount -o rw,remount /system;" + for apk in "${CUSTOM_LIST[@]}"; do + grep -qxF "$apk" deleted_apks.txt || echo "$apk" >> "deleted_apks.txt" + commandes+="echo \"rm -rf $apk\"; rm -rf \"$apk\";" + done + commandes+="mount -o ro,remount /system" + printf "\n${BRED}%s${NC}\n\n" "Check your phone: Magisk Manager is probably asking you to grand root permissions for ADB" + adb shell "su -c '$commandes'" + printf "\n${BRED}%s${NC}\n" "DONE" + printf "\n%s${BRED}%s${NC}\n" "A list of deleted apks has been backed-up in " "deleted_apks.txt" + printf "\n\e[5m%s\033[0m" "Press any key to continue" + read -n 1 -r -s fi } lists_selection() { - clear + clear -x + declare -a selection=() for ((i=1; i<=$#; i++)); do - echo "$i - ${!i}" + printf "%-2s%s\n" "$i" " - ${!i}" done - printf "${BRED}%s${NC} " "Your choice (e.g 1 2 3) :" + printf "\n${BRED}%s${NC} " "Your choice (e.g 1 2 3) :" read -r -a selection for list in "${selection[@]}"; do if (( list > $# )) || (( list < 1 )); then continue; fi - generate_custom_list "${!list}" && debloat_or_restore CUSTOM_LIST "${!list}" + debloat_or_restore "${!list}" done } list_installed_packages() { - clear + clear -x printf "\n${BRED}%s${NC}" "Search for packages (regex accepted): " read -r @@ -230,7 +441,7 @@ list_installed_packages() { } restore_backup() { - clear + clear -x printf "${BRED}%s${NC}" "Enter the path of the backup to restore : " read -r @@ -241,7 +452,7 @@ restore_backup() { } backup() { - clear + clear -x local backup=$(date +%Y-%m-%d-%H:%M:%S) adb backup -apk -all -system -f "${PHONE:-phone}-${backup}.adb" # -noshare option is default @@ -275,4 +486,76 @@ get_brand() { esac } +uad_recovery_mode() { + ROOT=1 + while true; do + clear -x + printf "\n${BBLUE}%s\n" "=========== MAIN MENU (RECOVERY MODE) ===========" + printf "%s\n" "# #" + printf "%-14s${NC}%s${BBLUE}%12s\n" "#" "1 - Restore APKs (Root)" "#" + printf "%-14s${NC}%s${BBLUE}%12s\n" "#" "2 - Debloat APKs (Root)" "#" + printf "%s\n" "# #" + printf "%-14s${NC}%s${BBLUE}%6s\n" "#" "X - Exit and reboot the phone" "#" + printf "%s\n" "# #" + printf "%s${NC}\n\n" "===================================================" + + read -r -p "Choose an action : " + + case $REPLY in + 1) { title="RESTORE"; RESTORE=1; };; + 2) { title="DEBLOAT"; RESTORE=0; };; + [Xx]) { adb reboot && exit 0; };; + *) exit + esac + + clear -x + printf "\n${BBLUE}%s\n" "================= $title (ROOT) ================" + printf "%s\n" "# #" + printf "%-14s${NC}%s${BBLUE}%17s\n" "#" "1 - $title an APK" "#" | awk '{print tolower($0)}' + printf "%-14s${NC}%s${BBLUE}%18s\n" "#" "2 - External list" "#" + ((RESTORE)) && printf "#${NC}%9s 3 - deleted_apks.txt ${BBLUE}%11s#\n" + printf "%s\n" "# #" + printf "%s\n${NC}" "===================================================" + + read -r -p "Choose an action : " + + if [[ $REPLY = 1 ]]; then + + printf "\n${BRED}%s${NC}" "Android path of the APK to $title: " + read -r path + + if [[ ! $path =~ ^/.*\.apk$ ]]; then + printf "\n${BRED}%s${NC}%s${BRED}%s${NC}%s\n" "$path" " doesn't look like a valid APK path" + sleep 3 && return 0 + fi + CUSTOM_LIST=("$path") + fi + + if [[ $REPLY = 2 ]]; then import_external_list && CUSTOM_LIST=("${EXTERNAL_LIST[@]}"); fi + if [[ $REPLY = 3 && $RESTORE -eq 1 ]]; then readarray -t CUSTOM_LIST < "deleted_apks.txt"; fi + + if [[ RESTORE -eq 0 ]]; then + backup_apks CUSTOM_LIST + printf "\n%s${BRED}%s${NC}%s\n\n" "Your apks has been backed-up in" " apks_backup/" " (in case you messed up)" + fi + + for p in "${CUSTOM_LIST[@]}"; do # $p = path/to/app.apk + local apk=$(echo "$p" | sed -r 's/.*\///g') # app.apk + local dir=$(dirname "$p") # path/to + + if [[ $RESTORE -eq 0 ]]; then + adb shell "rm -rf $p" && echo "rm -rf $p" + grep -qxF "$p" deleted_apks.txt || echo "$p" >> "deleted_apks.txt" + + else + echo "adb push apks_backup/$apk /\"$p\"" + if adb shell "mkdir -p $dir" && adb push "apks_backup/$apk" "/$p"; then + grep -qFv "$p" deleted_apks.txt > temp.tmp || touch temp.tmp; mv temp.tmp deleted_apks.txt + fi + fi + done + sleep 2 + done +} + main "$@"; exit \ No newline at end of file